【问题标题】:Encoding special chars, DOMDocument XML and PHP编码特殊字符、DOMDocument XML 和 PHP
【发布时间】:2019-07-08 10:55:36
【问题描述】:

使用以下字符:" & ' < > £ 进行测试。我的代码使用 PHP 和 DOMDocument 构建了一个 XML 文件。

<?php

 $xml = new DOMDocument();
 $xml->formatOutput = true;
 $root = $xml->createElement('Start_Of_XML');
 $xml->appendChild($root);

 $el = $xml->createElement($node,htmlspecialchars(html_entity_decode($value[$i],ENT_QUOTES,'UTF-8'),ENT_QUOTES,'UTF-8'));               
 $parent->appendChild($el);

?>

上面的htmlspecialchars() 方法将这些字符转换为:

" &amp;amp; ' &amp;lt; &amp;gt; £

分别。也就是说,双引号、撇号和井号无法编码。

如果我调整代码以使用 htmlentities() 代替:

<?
 $el = $xml->createElement($node,htmlentities(html_entity_decode($value[$i],ENT_QUOTES,'UTF-8'),ENT_QUOTES,'UTF-8'));

?>

字符被解析为:

" &amp;amp; ' &amp;lt; &amp;gt; &amp;pound;

因此,井号与其他符号一起被转换,但在保存 XML 时,引号和撇号再次无法编码。

搜索了几篇帖子后,我不知所措地找到了解决方案?

编辑:

使用Gordon's 答案作为基础,我得到了我正在寻找的结果,使用类似于https://3v4l.org/ZksrE 的东西

ThW 付出了巨大的努力。看起来还挺全面的。我将接受这个作为解决方案。谢谢。

【问题讨论】:

  • 看来createElement 可以方便地为您识别&amp;quot;&amp;#039 并将它们转换回原来的引号:3v4l.org/qof5l
  • 太棒了!请问如何重新转换它们?
  • 我尝试使用createTextNode(),但没有结果。 3v4l.org/WMBfW你能推我一下吗?
  • 等一下,我认为 Gordon 的回答可能会解决它stackoverflow.com/questions/2822774/…

标签: php xml


【解决方案1】:

DOMDocument::createElement() 的第二个参数被破坏 - 它只是部分转义,它不是 W3C DOM 标准的一部分。在 DOM 中,文本内容是一个节点。您可以创建它并将其附加到元素节点。这也适用于其他节点类型,如 CDATA 部分或 cmets。 DOMNode::appendChild() 返回附加的节点,因此您可以嵌套和链接调用。

此外,您还可以设置DOMElement::$textContent 属性。这将用单个文本节点替换所有后代节点。不要使用DOMElement::$nodeValue - 它与参数有相同的问题。

$document = new DOMDocument();
$document->formatOutput = true;
$root = $document->appendChild($document->createElement('foo'));
$root
   ->appendChild($document->createElement('one'))
   ->appendChild($document->createTextNode('"foo" & <bar>'));
$root
   ->appendChild($document->createElement('one'))
   ->textContent = '"foo" & <bar>';
$root
   ->appendChild($document->createElement('two'))
   ->appendChild($document->createCDATASection('"foo" & <bar>'));
$root
   ->appendChild($document->createElement('three'))
   ->appendChild($document->createComment('"foo" & <bar>'));

echo $document->saveXML();

输出:

<?xml version="1.0"?>
<foo>
  <one>"foo" &amp; &lt;bar&gt;</one>
  <one>"foo" &amp; &lt;bar&gt;</one>
  <two><![CDATA["foo" & <bar>]]></two>
  <three>
    <!--"foo" & <bar>-->
  </three>
</foo>

这将根据需要转义特殊字符(如&amp;&lt;)。引号确实需要被转义,所以它们不会。其他特殊字符取决于编码。

$document = new DOMDocument("1.0", "UTF-8");
$document
   ->appendChild($document->createElement('foo'))
   ->appendChild($document->createTextNode('äöü'));
echo $document->saveXML();

$document = new DOMDocument("1.0", "ASCII");
$document
   ->appendChild($document->createElement('foo'))
   ->appendChild($document->createTextNode('äöü'));
echo $document->saveXML();

输出:

<?xml version="1.0" encoding="UTF-8"?> 
<foo>äöü</foo> 
<?xml version="1.0" encoding="ASCII"?> 
<foo>&#228;&#246;&#252;</foo>

【讨论】:

  • 当你说:“DOMDocument::createElement() 的第二个参数被破坏了——它只是部分转义,它不是 W3C DOM 标准的一部分。”您是指使用htmlentities() 来编码特殊字符的幼稚或错误使用吗?
  • 他指的是使用DOMDocument::createElement()同时创建标签和填充值。这是一个non-standard feature,它没有在 PHP 中正确实现。
  • 它将转义 &lt;&gt;,因此将其视为文本,但它仍然希望您自己编码 &amp; 或希望实体引用。这就是 XML 片段的行为。 htmlentities()htmlspecialchars() 是字符串函数,与 DOM 无关。如果您使用 XML API,则不需要它们。
猜你喜欢
  • 2011-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-25
  • 1970-01-01
  • 2011-04-23
相关资源
最近更新 更多