使用PHP的DOM类替换DOMNode [英] DOMNode replacement with PHP's DOM classes

查看:96
本文介绍了使用PHP的DOM类替换DOMNode的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习使用PHP中提供的DOM *类,并注意到(我认为是)我的测试中的不规则。



给定文件, 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&amp;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>&nbsp;|&nbsp;</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&amp;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>&mdash;</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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆