使用PHP的DOM类替换DOMNode [英] DOMNode replacement with PHP's DOM classes
问题描述
给定文件, ZuqML_test_100.html
:
<!DOCTYPE html PUBLIC - // W3C // DTD XHTML 1.0 Strict // ENhttp://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">
< html xmlns =http://www.w3.org/1999/xhtmlxmlns:zuq =http:// localhost /〜/ zuqml>
< head>
< meta http-equiv =Content-Typecontent =text / html; charset = utf-8/>
< title> Untitled Document< / title>
< / head>
< body>
< h1>
< zuq:data name =siteHeader/>
< / h1>
< h2>
< zuq:data name =pageHeaderName/>
< span>& nbsp; |& nbsp;< / span>
< zuq:data name =pageHeaderTitle/>
< / h2>
< zuq:region name =post>
< zuq:param name =onEmpty>
< div class =post noposts>
< p>目前没有任何要显示的帖子。< / p>
< / div>
< / zuq:param>
< div class =post>
< h3>< zuq:data name =postHeader/>< / h3>
< p>
< zuq:data name =postText>
< zuq:format type =trim>
< zuq:param name =length> 300< / zuq:param>
< zuq:param name =append>
< a>
< zuq:attr name =href>
./?action=viewpost&id=<zuq:data name =postId/>
< / zuq:attr>
< zuq:data name =postAuthor/>
< / a>
< / zuq:param>
< / zuq:format>
< / zuq:data>
< / p>
< / div>
< / zuq:region>
< / body>
< / html>
我试图替换所有< zuq:data />
节点带有一个简单的文本节点,值为 foo
。我正在使用以下代码片段:
$ root = new DOMDocument();
@ $ root-> load('ZuqML_test_100.html');
foreach($ root-> getElementsByTagNameNS($ root-> lookupNamespaceURI('zuq'),'data')作为$ node){
$ node-> parentNode-> ; replaceChild($ node-> ownerDocument-> createTextNode('foo'),$ node);
}
echo $ root-> saveXML();
它的作品类型,但是我的输出仍然包含< zuq :data />
节点,如下所示:
<?xml version =1.0 >?;
<!DOCTYPE html PUBLIC - // W3C // DTD XHTML 1.0 Strict // ENhttp://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">
< html xmlns =http://www.w3.org/1999/xhtmlxmlns:zuq =http://ichorworkstudios.no-ip.org/~/zuqml>
< head>
< meta http-equiv =Content-Typecontent =text / html; charset = utf-8/>
< title> Untitled Document< / title>
< / head>
< body>
< h1>
foo
< / h1>
< h2>
< zuq:data name =pageHeaderName>< / zuq:data>
< span>& mdash;< / span>
foo
< / h2>
< zuq:region name =post>
< zuq:param name =onEmpty>
< div class =post noposts>
< p>目前没有任何要显示的帖子。< / p>
< / div>
< / zuq:param>
< div class =post>
< h3>< zuq:data name =postHeader>< / zuq:data>< / h3>
< p>
foo
< / p>
< / div>
< / zuq:region>
< / body>
< / html>
为什么有些< zuq:data />
节点遗留下来?
我认为这与迭代的方式有关。您正在改变结果列表,因为它被反复,所以它绕开了(副作用)。尝试将您的循环更改为:
$ nodes = $ root-> getElementsByTagNameNS($ root-> lookupNamespaceURI('zuq '),'data');
$ i = $ nodes-> length - 1;
while($ i> = 0){
$ node = $ nodes-> item($ i);
$ node-> parentNode-> replaceChild(
$ node-> ownerDocument-> createTextNode('foo'),
$ node
);
$ i--;
}
基本上,它只是循环遍历节点列表,这样当节点被删除,它们从结尾而不是开始删除...
I'm learning to work with the DOM* classes available in PHP, and have noticed (what I think is) an irregularity in my testing.
Given this document, ZuqML_test_100.html
:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:zuq="http://localhost/~/zuqml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
</head>
<body>
<h1>
<zuq:data name="siteHeader" />
</h1>
<h2>
<zuq:data name="pageHeaderName" />
<span> | </span>
<zuq:data name="pageHeaderTitle" />
</h2>
<zuq:region name="post">
<zuq:param name="onEmpty">
<div class="post noposts">
<p>There are no posts to show at this time.</p>
</div>
</zuq:param>
<div class="post">
<h3><zuq:data name="postHeader" /></h3>
<p>
<zuq:data name="postText">
<zuq:format type="trim">
<zuq:param name="length">300</zuq:param>
<zuq:param name="append">
<a>
<zuq:attr name="href">
./?action=viewpost&id=<zuq:data name="postId" />
</zuq:attr>
<zuq:data name="postAuthor" />
</a>
</zuq:param>
</zuq:format>
</zuq:data>
</p>
</div>
</zuq:region>
</body>
</html>
I'm trying to replace all <zuq:data />
nodes with a simple text node with the value foo
. I'm doing so with the following snippet:
$root = new DOMDocument();
@$root->load('ZuqML_test_100.html');
foreach($root->getElementsByTagNameNS($root->lookupNamespaceURI('zuq'), 'data') as $node){
$node->parentNode->replaceChild($node->ownerDocument->createTextNode('foo'), $node);
}
echo $root->saveXML();
It sort of works, however my output still appears to contain <zuq:data />
nodes, as shown here:
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:zuq="http://ichorworkstudios.no-ip.org/~/zuqml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
</head>
<body>
<h1>
foo
</h1>
<h2>
<zuq:data name="pageHeaderName"></zuq:data>
<span>—</span>
foo
</h2>
<zuq:region name="post">
<zuq:param name="onEmpty">
<div class="post noposts">
<p>There are no posts to show at this time.</p>
</div>
</zuq:param>
<div class="post">
<h3><zuq:data name="postHeader"></zuq:data></h3>
<p>
foo
</p>
</div>
</zuq:region>
</body>
</html>
Why is it that some <zuq:data />
nodes are left behind?
I think it has to do with how you're iterating. You're changing the result list as it's being iterated against, so it winds up breaking (side-effects). Try changing your loop to this:
$nodes = $root->getElementsByTagNameNS($root->lookupNamespaceURI('zuq'), 'data');
$i = $nodes->length - 1;
while ($i >= 0) {
$node = $nodes->item($i);
$node->parentNode->replaceChild(
$node->ownerDocument->createTextNode('foo'),
$node
);
$i--;
}
Basically, it just iterates backwards over the list of nodes, so that when nodes are removed, they are removed from the end rather than the beginning...
这篇关于使用PHP的DOM类替换DOMNode的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!