使用PHP的DOMDocument使用编码文本保存XML

时间:2015-08-11 07:34:26

标签: php xml domdocument decode encode

我正在尝试使用DOMDocument()来加载一些XML。我想用编码值保存XML,但在调用saveXML()时它会不断解码。

请参阅以下代码:

 $xml_str = "<Name>o&#39;rielly, o-no, s~sdf&quot;sdf&#39; one test</Name>";
 $dom = new DOMDocument();
 $dom->formatOutput = TRUE;
 $dom->preserveWhiteSpace = FALSE;
 if($dom->loadXML($xml_str)) {                      
      $saved_XML     = $dom->saveXML();
      print_r("xml -> {$saved_XML}\n");  
 }

print_r语句将返回:

 <?xml version="1.0"?> 
 <Name>o'rielly, o-no, s~sdf"sdf' one test</Name>

我想让它回归:

 <?xml version="1.0"?> 
 <Name>o&#39;rielly, o-no, s~sdf&quot;sdf&#39; one test</Name>

这可能吗?

欢迎任何帮助。谢谢。

1 个答案:

答案 0 :(得分:1)

DOM将逃脱所有需要的角色,但不会逃脱其他角色。文本节点中的引号不需要转义,因此DOM不会转义它们。如果加载XML解析器,结果将是相等的。

这取决于预期的结果。如果要读取特殊字符,只需让DOM转义所需的字符并忽略其他字符。它将使XML更易于阅读和更小。如果您需要阅读实体,则必须使用CDATA部分或对其进行编码。

$xml = <<<'XML'
<Names>
   <Name>o'rielly, o-no, s~sdf"sdf' one test</Name>
   <Name>o&#39;rielly, o-no, s~sdf&quot;sdf&#39; one test</Name>
   <Name><![CDATA[o&#39;rielly, o-no, s~sdf&quot;sdf&#39; one test]]></Name>
   <Name>o&amp;#39;rielly, o-no, s~sdf&amp;quot;sdf&amp;#39; one test</Name>
</Names>
XML;

$dom = new DOMDocument();
$dom->loadXml($xml);
$xpath = new DOMXPath($dom);

echo "Default:\n";
var_dump($xpath->evaluate('string(//Name[1])'));
echo "Entities:\n";
var_dump($xpath->evaluate('string(//Name[2])'));
echo "CDATA Section:\n";
var_dump($xpath->evaluate('string(//Name[3])'));
echo "Encoded Entities:\n";
var_dump($xpath->evaluate('string(//Name[4])'));

输出:

Default:
string(35) "o'rielly, o-no, s~sdf"sdf' one test"
Entities:
string(35) "o'rielly, o-no, s~sdf"sdf' one test"
CDATA Section:
string(48) "o&#39;rielly, o-no, s~sdf&quot;sdf&#39; one test"
Encoded Entities:
string(48) "o&#39;rielly, o-no, s~sdf&quot;sdf&#39; one test"

如果使用正确的create *方法创建节点,DOM将负责编码,以便您可以读取保存的相同值。

$dom = new DOMDocument();
$dom->formatOutput = TRUE;
$root = $dom->appendChild($dom->createElement('Names'));
$root
  ->appendChild($dom->createElement('Name'))
  ->appendChild($dom->createTextNode("O'Reilly"));
$root
  ->appendChild($dom->createElement('Name'))
  ->appendChild($dom->createTextNode("O&#39;Reilly"));
$root
  ->appendChild($dom->createElement('Name'))
  ->appendChild($dom->createCDataSection("O&#39;Reilly"));

echo $dom->saveXml();

输出:

<?xml version="1.0"?>
<Names>
  <Name>O'Reilly</Name>
  <Name>O&amp;#39;Reilly</Name>
  <Name><![CDATA[O&#39;Reilly]]></Name>
</Names>