2009-11-14 45 views
3

我使用以下方法来获得一个html文件到DOM:PHP DOM - 访问新增节点

$dom = new domDocument('1.0', 'utf-8'); 
$dom->loadHTML($html) 

然后我加入一些新的内容元素在html:

$element = $dom->getElementById('mybox'); 
$f = $dom->createDocumentFragment(); 
$f->appendXML('<div id="newbox">foo</div>'); 
$element->appendChild($f); 

但是如果我现在想要操纵#newbox,我无法做到这一点,因为我无法通过getElementById()访问它。为了做到这一点我必须做以下(与新的HTML重装):

$html = $dom->saveHTML(); 
$dom->loadHTML($html) 

,工作正常,但不必每个DOM操作之间做到这一点的时候,就变成昂贵的性能代价。

有没有更好的方法来“刷新”DOM,使其与新添加的元素一起工作?

在此先感谢! :)

+0

我很好奇将提供什么答案;我想......必须有一个合适的方法来做到这一点,但现在无法想到任何事情。问题中的细节:$ dom变量在dom-> getElementBYId('mybox')中缺少其美元前缀;声明。 – kander 2009-11-14 03:02:07

回答

1

在保存和加载方法,你也可以尝试Document.normalizeDocument。这应该修复文档,就好像它已经保存了循环一样,而没有真正的序列化。应该做的一件事是重新计算文档类型的属性的isID-你希望希望已经被设置为HTML doctype之一(将id定义为值类型的属性ID)loadHTML

(还有Element.setIdAttribute可用于声明Attr的一个实例包含的ID,但是这是没有用的你,因为你必须先弄个)

我的天堂我没有测试过这个,如果PHP没有正确地实现这个DOM Level 3 Core的东西,它并不会让我感到惊讶。根据我对the spec for isId的解释,我认为它应该已经自动拾取了id类型定义。 (我自己的DOM实现肯定会。)但是,在这种情况下,你的代码会起作用。我认为appendXML毕竟是一种非标准的方法,所以没什么可说的,它必须解决像loadXMLloadHTML那样的类型定义。

所以,也许一个解决方法是一个更好的计划。您可以使用DOMXPath来选择@id属性的元素,而不是真实ID。当然这会比getElementById慢得多,但希望比normalizeDocument更快。

或者只是丢失XML字符串索引并坚持DOM方法,如果可以的话;那么保持对创建元素的引用是微不足道的。 (如果您发现DOM方法对于您创建的内容数量过于罗嗦,则可以使用帮助函数更快地创建元素。)

+0

感谢回复bobince, 看起来像normalizeDocument没有做到这一点。 我同意你在添加新内容时坚持使用DOM方法是最好的,但在这种情况下,它必须接受字符串,除非我构建了一些递归函数来将正确的DOM排除在字符串之外,但我想它可能会最终只需使用与现在重新加载一样多的资源。 – Tommy 2009-11-14 23:00:54

+0

是啊,惭愧...仍然,XPath的''''''[id ='newbox']'解决方法应该可以。假设它与DocumentFragment一起作为上下文节点,它应该是这样的,但是,我还没有在PHP上进行过测试...... ;-) – bobince 2009-11-14 23:34:46

0

我知道的唯一一件事情可以很好地处理。 nicely是蟒蛇的美丽汤。 DOM全部分成了一个分析树,你可以添加或取消,你可以编写一个python脚本来处理html,然后通过数据库或系统调用来协调脚本。或者服务器端JavaScript可能值得研究。