Я делаю XML-документ для покупок в Google, и у меня возникли проблемы с кодировкой описания продуктов. Я пробовал разные подходы с str_replace
и избегая некоторых персонажей, utf8_encode
, iconv
и некоторые пользовательские функции, но все сгенерированные ошибки кодирования. Потом я нашел кого-то, кто использовал createTextNode
и это, казалось, работало на меня, я не получил ошибок.
Единственная проблема, с которой я столкнулся, это то, что я не могу получить createTextNode
в правильном пространстве имен (надеюсь, я говорю, что правильно).
Это код, который работал, но не сработал в описании некоторых продуктов из-за проблем с кодировкой:
$addProduct->appendChild($domtree->createElementNS($xmlns['atom'], 'description', 'test content'));
Это создает правильную строку:
<description>test content</description>
Теперь я хочу использовать createTextNode
код, но не могу заставить его работать с правильными тегами. Это работает:
$addProduct->appendChild($domtree->createTextNode('test content'));
Но это просто помещает контент в мою основную запись, в то время как он должен находиться между тегами описания.
Как я могу поместить это в теги описания?
Или, если вы знаете хороший способ решения проблем кодирования при использовании моего старого кода, это тоже хорошо.
Вот весь код, который я использую:
function function_xml_entities($text = null, $charset = 'ISO-8859-1'){
$text = htmlentities($text, ENT_COMPAT, $charset, false);
$arr_xml_special_char = array(""","&","'","<",">");
$arr_xml_special_char_regex = "(?";
foreach($arr_xml_special_char as $key => $value){
$arr_xml_special_char_regex .= "(?!$value)";
}
$arr_xml_special_char_regex .= ")";
$pattern = "/$arr_xml_special_char_regex&([a-zA-Z0-9]+;)/";
$replacement = '&${1}';
return preg_replace($pattern, $replacement, $text);
}
function function_html2text($html = null){
$tags = array (
0 => '~<h[123][^>]+>~si',
1 => '~<h[456][^>]+>~si',
2 => '~<table[^>]+>~si',
3 => '~<tr[^>]+>~si',
4 => '~<li[^>]+>~si',
5 => '~<br[^>]+>~si',
6 => '~<p[^>]+>~si',
7 => '~<div[^>]+>~si',
);
$html = preg_replace($tags,"\n",$html);
$html = preg_replace('~</t(d|h)>\s*<t(d|h)[^>]+>~si',' - ',$html);
$html = preg_replace('~<[^>]+>~s','',$html);
// reducing spaces
$html = preg_replace('~ +~s',' ',$html);
$html = preg_replace('~^\s+~m','',$html);
$html = preg_replace('~\s+$~m','',$html);
// reducing newlines
$html = preg_replace('~\n+~s',"\n",$html);
return $html;
}
$sql_products = "QUERY WHICH IS NOT RELEVANT";
$result_products = mysql_query($sql_products);
//create a dom document with encoding utf8
$domtree = new DOMDocument('1.0', 'UTF-8');
//create the root element of the xml tree
$xmlRoot = $domtree->createElement("feed");
$xmlRoot = $domtree->appendChild($xmlRoot);
//create a dom document with encoding utf8
$domtree = new DOMDocument('1.0', 'UTF-8');
//create the root element of the xml tree
$xmlns = array('atom' => 'http://www.w3.org/2005/Atom','g' =>'http://base.google.com/ns/1.0');
$xmlRoot = $domtree->appendChild($domtree->createElementNS($xmlns['atom'], 'feed'));
$xmlRoot->setAttributeNS($xmlns['g'], 'g:dummy', ''); //add a dummy attribute to add the google namespace to the document element
$xmlRoot->removeAttribute('g:dummy'); //remove dummy attribute
//Standard things like title
$xmlRoot->appendChild($domtree->createElement('title', 'title'));
$link = $xmlRoot->appendChild($domtree->createElement('link'));
$link->setAttribute('rel', 'self');
$link->setAttribute('href', $global_websitenaam_include);
$xmlRoot->appendChild($domtree->createElement('updated', date('Y-m-d H:i:s')));
$addAuthor = $xmlRoot->appendChild($domtree->createElement("author"));
$addAuthor->appendChild($domtree->createElement('name', 'author name'));
$xmlRoot->appendChild($domtree->createElement('id', 'tag:website.com,'.date('Y-m-d')));
//Producten doorlopen
while($product = mysql_fetch_assoc($result_products)){
//HERE ARE OTHER QUERIES AND DEFINING VARIABLES WHICH AREN'T RELEVANT TO THE CODE
$product_content = function_xml_entities(substr_replace(str_replace(' ',' ', function_html2text($product['content'])), "", 5000));
// create the products
$addProduct = $xmlRoot->appendChild($domtree->createElementNS($xmlns['atom'], "entry"));
$addProduct->appendChild($domtree->createElementNS($xmlns['atom'], 'id', $product['id']));
$addProduct->appendChild($domtree->createElementNS($xmlns['atom'], 'title', substr_replace($product['name'], "", 150)));
$linkProd = $addProduct->appendChild($domtree->createElement('link'));
$linkProd->setAttribute('href', $global_websitenaam_include.'/'.rawurlencode($product['category_slug']).'/'.rawurlencode($product['slug']));
$addProduct->appendChild($domtree->createElementNS($xmlns['g'], 'g:price', number_format($product_price, 2, ',', '.')));
$addProduct->appendChild($domtree->createElementNS($xmlns['g'], 'g:condition', $condition_product));
$addProduct->appendChild($domtree->createElementNS($xmlns['g'], 'g:brand', substr_replace($product['manufacturer_name'], "", 70)));
$addProduct->appendChild($domtree->createElementNS($xmlns['g'], 'g:mpn', $product['typenumber']));
$addProduct->appendChild($domtree->createElementNS($xmlns['g'], 'g:ean', $product['ean']));
$addProduct->appendChild($domtree->createElementNS($xmlns['g'], 'g:image_link', $product_image));
$addProduct->appendChild($domtree->createElementNS($xmlns['g'], 'g:product_type', 'Huis & Tuin > '.$parentcategory_name.$product['category_name']));
$addProduct->appendChild($domtree->createElementNS($xmlns['g'], 'g:availability', $product_stock));
$addProduct->appendChild($domtree->createElementNS($xmlns['g'], 'g:manufacturer', $product['supplier_name']));
$addProduct->appendChild($domtree->createElementNS($xmlns['g'], 'g:weight', $product['weight']));
$addProduct->appendChild($domtree->createElementNS($xmlns['g'], 'g:featured_product', $product_advertisement));
$addProduct->appendChild($domtree->createElementNS($xmlns['g'], 'g:size', $product['size']));
$addProductShipping = $addProduct->appendChild($domtree->createElement("g:shipping"));
$addProductShipping->appendChild($domtree->createElement('g:country', 'NL'));
$addProductShipping->appendChild($domtree->createElement('g:service', 'Standaard'));
$addProductShipping->appendChild($domtree->createElement('g:price', number_format($shipment_price, 2, ',', '.')));
$addProduct->appendChild($domtree->createElementNS($xmlns['atom'], 'description', $product_content));
//$addProduct->appendChild($domtree->createTextNode($product_content));
}
//get the xml printed
header("content-type: text/xml; charset: utf-8");
$domtree->formatOutput = true;
echo $domtree->saveXML();
Узлы символьных узлов не имеют пространства имен. Вот два типа их. Текстовые узлы, которые кодируют специальные символы XML и разделы CDATA, которые используют специальный синтаксис. Оба могут быть использованы для atom:description
а также atom:summary
, Ожидаемый контент (для Atom Parser) зависит от type
приписывать.
По умолчанию просто text
, html
означает, что он ожидает фрагмент HTML, закодированный как текст, xhtml
являются дочерними узлами в пространстве имен XHTML.
Вы не должны использовать аргумент содержимого createElement()/createElementNS()
или установите свойство $ nodeValue, за исключением случаев, когда вы уверены, что в значении нет специальных символов (пустая строка, целые числа, …). Они используют неработающую кодировку. Создайте узлы персонажа, используя DOMDocument::createTextNode()
или же DOMDocument::createCDATASection()
,
Вот небольшой пример:
$xmlns = [
'atom' => 'http://www.w3.org/2005/Atom'
];
$htmlFragment = '<div>Description HTML Fragment</div>';
$document = new DOMDocument();
$entry = $document->appendChild(
$document->createElementNS($xmlns['atom'], 'entry')
);
$summary = $entry->appendChild(
$document->createElementNS($xmlns['atom'], 'summary')
);
$summary->setAttribute('type', 'text');
$summary->appendChild(
$document->createTextNode('Summary Text')
);
$description = $entry->appendChild(
$document->createElementNS($xmlns['atom'], 'description')
);
$description->setAttribute('type', 'html');
$description->appendChild(
$document->createCDATASection($htmlFragment)
);
$document->formatOutput = TRUE;
echo $document->saveXml();
Выход:
<?xml version="1.0"?>
<entry xmlns="http://www.w3.org/2005/Atom">
<summary type="text">Summary Text</summary>
<description type="html"><![CDATA[<div>Description HTML Fragment</div>]]></description>
</entry>
Других решений пока нет …