【问题标题】:PHP DOMDocument createTextNode with namespacePHP DOMDocument createTextNode 与命名空间
【发布时间】:2017-03-09 10:44:57
【问题描述】:

我正在为谷歌购物制作一个 xml 文档,但在产品描述的编码方面遇到了问题。我尝试了使用str_replace 和转义一些字符、utf8_encodeiconv 和一些自定义函数的不同方法,但都产生了编码错误。然后我找到了使用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("&quot;","&amp;","&apos;","&lt;","&gt;");
    $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 = '&amp;${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('&nbsp;',' ', 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 &amp; Tuin &gt; '.$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();       

【问题讨论】:

    标签: php xml domdocument google-shopping


    【解决方案1】:

    字符节点节点没有命名空间。这里有两种类型。文本节点,对 XML 特殊字符和 CDATA 部分进行编码,使用特殊语法。两者都可用于atom:descriptionatom:summary。预期的内容(用于 Atom 解析器)取决于 type 属性。

    默认只是texthtml 意味着它需要一个编码为文本的 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>
    

    【讨论】:

    • 感谢您的详尽回答!它帮助我更好地理解了 domdocument 结构。
    猜你喜欢
    • 2018-02-11
    • 2019-03-25
    • 2012-10-24
    • 1970-01-01
    • 2012-02-05
    • 1970-01-01
    • 1970-01-01
    • 2014-04-14
    • 1970-01-01
    相关资源
    最近更新 更多