【发布时间】:2013-11-21 06:50:50
【问题描述】:
用PHP说明:normalizeDocument()方法存在BUG,或者缺少“刷新”方法,因为更改后DOM一致性丢失(甚至只是属性更改)。 .. 因此,您使用 LIBXML2 实现的任何“带有 DOM 更改”的算法在某些情况下有效,有时无效,是不可预测的! (?)
$doc->LoadXML($doc->saveXML()); 的“刷新”是一种变通方法,并且在使用 DOM 的工作流程中失去了性能...一个子问题:我需要刷新 DOM 的所有时刻?
$XML = '
<html>
<h1>Hello</h1>
<ol>
<li>test (no id)</li>
<li xml:id="i2">test i2</li>
</ol>
</html>
';
$doc = new DOMDocument;
$doc->LoadXML($XML);
doSomeChange($doc); // here DOM is modified
print $doc->saveXML(); // show new DOM state
$doc->normalizeDocument(); // NOT REFRESHING!?!
var_dump($doc->getElementById('i2')); //NULL!??! is a BUG!
//CAN_NOT_doMORESomeChange($doc);
$doc->LoadXML($doc->saveXML()); // only way to refresh?
print $doc->getElementById('i2')->tagName; //OK, is there
// illustrating attribute modification:
function doSomeChange(&$dom) {
$max = 0;
$xp = new DOMXpath($dom);
foreach(iterator_to_array($xp->query('/html/* | //li')) as $e) {
$max++;
$e->setAttribute('xml:id',"i$max");
}
print "\ncmpDOM='".($xp->document === $dom)."'\n"; // after @ThomasWeinert
}
所以,输入是 $XML,输出是
<html>
<h1 xml:id="i1">Hello</h1>
<ol xml:id="i2">
<li xml:id="i3">test (no id)</li>
<li xml:id="i4">test i2</li>
</ol>
</html>
NULL
ol
NULL 是错误(参见代码 cmets)。
PS:如果我将输入行 <li xml:id="i2">test i2</li> 更改为 <li>test i2</li>,算法会按预期工作(!),因此是不可预测的。
相关问题:In DomDocument, reuse of DOMXpath, it is stable?PHP DomDocument, reuse of XSLTProcessor, it is stable/secure?
【问题讨论】:
-
这可能是
normalizeDocument没有重新解析 xml:id 属性 - 这个问题是否发生在任何其他 DOM 操作上?这个具体的例子可以通过使用loadHTML($xml)和id(而不是xml:id)属性来解决,不用normalizeDocument。 -
感谢您的笔记。好吧,“不重新解析 xml:id 属性”,为什么?是的,任何其他修改(removeChild、replaceChild 等)都会出现问题:DOM 行为将是不可预测的。我使用具有许多“doMORESomeChange()”函数序列的程序...我的具体问题是处理XML JATS documents,大文档,因此很难在此处复制/粘贴测试环境...
xml:id使用正确,并且是一个很好的例子——我现在没有另一个“如此短的 XML”来显示更多的插图。 -
尽管the documentation 说“这个方法就像你保存然后加载文档一样”,
normalizeDocument实际上只适用于collapsing adjacent text nodes。 -
...谢谢(!)。嗯,是的,所以,没有“刷新 DOM”的内部方法:只有 saveXML/loadXML 的蛮力(并且需要重新配置 DOM 属性)。
标签: refresh domdocument libxml2