如何防止DOMDocument保存< as<

时间:2010-08-06 13:16:13

标签: php xml simplexml domdocument

我正在使用simpleXML在我的一个XML文档中添加子节点...当我在simpleXML对象上执行print_r时,<仍然显示为<在视图源中。但是,在使用DOMDocument将此对象保存回XML后,<转换为&lt;>转换为&gt;

有关如何更改此行为的任何想法?我尝试添加dom->substituteEntities = false;,但这没有用。

    //Convert SimpleXML element to DOM and save
    $dom = new DOMDocument('1.0');
    $dom->preserveWhiteSpace = false;
    $dom->formatOutput = false;
    $dom->substituteEntities = false;
    $dom->loadXML($xml->asXML());
    $dom->save($filename);

这是我使用&lt;:

的地方
$new_hint = '<![CDATA[' . $value[0] . ']]>';               
$PrintQuestion->content->multichoice->feedback->hint->Passage->Paragraph->addChild('TextFragment', $new_hint);

问题是,我使用简单的XML来迭代XML文档中的某些节点,如果属性与给定的ID匹配,则会在CDATA中添加特定的子节点。然后在所有处理之后,我使用DOMDocument将XML保存回文件,这是&lt;被转换为&amp; lt等。

这是我整个班级文件的链接,因此您可以更好地了解我想要完成的任务。具体请参考底部的hint_insert()方法。

http://pastie.org/1079562

2 个答案:

答案 0 :(得分:10)

SimpleXML和php5的DOM module使用相同的文档内部表示(由libxml推动)。您可以在两个apis之间切换,而无需通过simplexml_import_dom()和dom_import_simplexml()重新解析文档。
即如果您真的想/必须使用SimpleXML api执行迭代,找到元素后,您可以切换到相同文档中的DOM api和create the CData section

<?php
$doc = new SimpleXMLElement('<a>
  <b id="id1">a</b>
  <b id="id2">b</b>
  <b id="id3">c</b>
</a>');


foreach( $doc->xpath('b[@id="id2"]') as $b ) {
  $b = dom_import_simplexml($b);
  $cdata = $b->ownerDocument->createCDataSection('0<>1');
  $b->appendChild($cdata);
  unset($b);
}

echo $doc->asxml();

打印

<?xml version="1.0"?>
<a>
  <b id="id1">a</b>
  <b id="id2">b<![CDATA[0<>1]]></b>
  <b id="id3">c</b>
</a>

答案 1 :(得分:3)

问题在于您可能将其添加为字符串而不是元素。

所以,而不是:

$simple->addChild('foo', '<something/>');

将被视为文本:

$child = $simple->addChild('foo');
$child->addChild('something');

您不能在XML文档的正文中包含文字<,除非它是标记的开头。

编辑:根据您在评论中描述的内容,我认为您已经过了:

DomDocument::createCDatatSection()

$child = $dom->createCDataSection('your < cdata > body ');
$dom->appendChild($child);

编辑2:阅读完编辑后,我只能说一件事:

You're doing it wrong...您不能将元素添加为另一个元素的字符串值。对不起,你就是不能。这就是它逃避的原因,因为DOM和SimpleXML确保您始终创建有效的XML。您需要将元素创建为对象...因此,如果要创建CDATA子元素,则必须执行以下操作:

$child = $PrintQuestion.....->addChild('TextFragment');
$domNode = dom_import_simplexml($child);
$cdata = $domNode->ownerDocument->createCDataSection($value[0]); 
$domNode->appendChild($cdata);

这就是应该有的......