使用DomDocument替换所有标签标签与h4标签 [英] Use DomDocument to replace all header tags with the h4 tags

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

问题描述

我已经使用DomDocument到GetElementById。它已经选择了一个div。我需要用h4标签替换该div内的所有标题。

解决方案

您还没有清楚你的问题具体的问题是你遇到了。我会假设有两个部分可能会导致一些问题。



第一个将是如何获取所有要重命名的元素的手而第二个则是如何重命名一个元素。



获取DOMDocument的标题元素



首先:要选择所有标题元素,您需要选择所有标签,标题元素(h1至h6)。结合条件,他们还需要具有特定id属性的div标签的孩子,这似乎是一个相当复杂的事情。然而,使用xpath查询,它仍然只是直接的。



示例我的代码示例我选择了id内容,并且以下xpath表达式查询所有标题元素:

 
// div [@ id =content] // h1
| // div [@ id =content] // h2
| // div [@ id =content] // h3
| // div [@ id =content] / / h4
| // div [@ id =content] // h5
| // div [@ id =content] // h6

如果我在这个网站上运行(在我回答之前),它会创建以下标签列表:

 找到8个元素:
#00:< h1>
#01:< h2>
#02:< h2>
#03:< h3>
#04:< h3>
#05:< h3>
#06:< h2>
#07:< h4>

正如此演示一样,使用xpath查询甚至不同元素的列表以及特定条件可以创建具有id的div的小孩。这段代码一目了然:

  $ url ='http://stackoverflow.com/questions/16307103/use-domdocument-更换的-所有报头标签与 - 的-H4标签; 

$ dom = new DOMDocument();
$ internalErrorsState = libxml_use_internal_errors(true);
$ dom-> loadHTMLFile($ url);
libxml_use_internal_errors($ internalErrorsState);
$ xpath = new DOMXPath($ dom);

$ expression ='

// div [@ id =content] // h1
| // div [@ id =content ] // h2
| // div [@ id =content] // h3
| // div [@ id =content] // h4
| // div [@ id =content] // h5
| // div [@ id =content] // h6
)';

$ elements = $ xpath-> query($ expression);
echoFound,$ elements-> length,elements:\\\
;
foreach($ elements as $ index => $ element){
printf(#%02d:<%s> \\\
,$ index,$ element-> tagName)
}



重命名一个DOMElement



那么第二个问题呢,关于重命名元素呢?



开箱即用的DOMDocumet不支持这个。有一个方法stub( DOMDocument :: renameNode();在当前的PHP手册中未记录),但是如果您调用它,则会收到一条警告,指出它未实现: p>


警告:DOMDocument :: renameNode():尚未实现


相反,需要滚动自己的版本。这是它的工作原理:由于您无法使用DOMDocument重命名元素,所以您可以做的就是使用重命名的名称创建一个新元素,并复制该节点以将其所有属性和子项重命名为其中,然后将其替换为重命名为浅拷贝。这通过以下方法完成:

  / ** 
*重命名DOM文档中的一个节点。
*
* @param DOMElement $ node
* @param string $ name
*
* @return DOMNode
* /
function dom_rename_element (DOMElement $ node,$ name){
$ renamed = $ node-> ownerDocument-> createElement($ name);

foreach($ node->属性为$属性){
$ renamed-> setAttribute($ attribute-> nodeName,$ attribute-> nodeValue);
}

while($ node-> firstChild){
$ renamed-> appendChild($ node-> firstChild);
}

return $ node-> parentNode-> replaceChild($ renamed,$ node);
}

将它与 foreach 循环从上面,输出标签名旁边,他们也可以重命名:

  $ elements = $ xpath - >查询($表达); 
echoFound,$ elements-> length,elements:\\\
;
foreach($ elements as $ index => $ element){
printf(#%02d:<%s> \\\
,$ index,$ element-> tagName)
dom_rename_element($ element,'h4');
#################################
}

然后,再次查询xpath表达式将仅导致h4标签:

  $ elements = $ xpath-> query($ expression); 
echoFound,$ elements-> length,elements:\\\
;
foreach($ elements as $ index => $ element){
printf(#%02d:<%s> \\\
,$ index,$ element-> tagName)
}

输出:

 找到8个元素:
#00:< h1>
#01:< h2>
#02:< h2>
#03:< h3>
#04:< h3>
#05:< h3>
#06:< h2>
#07:< h4>



完整代码示例



完整的代码示例及其输出一目了然:

 <?php 
/ **
*使用DomDocument替换所有标签标签与h4标签
* @link http://stackoverflow.com/q/16307103/367456
* /
$ url ='http:// stackoverflow.com/questions/16307103/use-domdocument-to-replace-all-header-tags-with-the-h4-tags';

$ dom = new DOMDocument();
$ internalErrorsState = libxml_use_internal_errors(true);
$ dom-> loadHTMLFile($ url);
libxml_use_internal_errors($ internalErrorsState);
$ xpath = new DOMXPath($ dom);

$ expression ='

// div [@ id =content] // h1
| // div [@ id =content ] // h2
| // div [@ id =content] // h3
| // div [@ id =content] // h4
| // div [@ id =content] // h5
| // div [@ id =content] // h6
)';

$ elements = $ xpath-> query($ expression);
echoFound,$ elements-> length,elements:\\\
;
foreach($ elements as $ index => $ element){
printf(#%02d:<%s> \\\
,$ index,$ element-> tagName)
dom_rename_element($ element,'h4');
}

$ elements = $ xpath-> query($ expression);
echoFound,$ elements-> length,elements:\\\
;
foreach($ elements as $ index => $ element){
printf(#%02d:<%s> \\\
,$ index,$ element-> tagName)
}

/ **
*重命名DOM文档中的一个节点。
*
* @param DOMElement $ node
* @param string $ name
*
* @return DOMNode
* /
function dom_rename_element (DOMElement $ node,$ name){
$ renamed = $ node-> ownerDocument-> createElement($ name);

foreach($ node->属性为$属性){
$ renamed-> setAttribute($ attribute-> nodeName,$ attribute-> nodeValue);
}

while($ node-> firstChild){
$ renamed-> appendChild($ node-> firstChild);
}

return $ node-> parentNode-> replaceChild($ renamed,$ node);
}

如果你尝试了,你可能会注意到现在,在我的答案之后,标题元素的数量已经改变。我希望这是有帮助的!


I've used DomDocument to to GetElementById. It has selected a div. I need to replace all the header tags within that div with the h4 tag.

解决方案

You have not made clear in your question what the concrete problem is you run into. I would assume that there are two parts that could cause you some questions marks.

The first one would be how to get the hand on all the elements that you want to rename and the second one is actually how to rename an element.

Get Heading Elements of a DOMDocument

So first things first: To select all the header elements you need to select all tags that are Heading elements (h1 to h6). Combined with the condition that they also need to be children of the div tag with a specific id attribute this seems like a rather complicate thing to do. However with an xpath query, it is still merely straight forward.

Exemplary for my code examples I have choosen the id `"content" and the following xpath expression queries all heading elements:

(
    //div[@id="content"]//h1
    |//div[@id="content"]//h2
    |//div[@id="content"]//h3
    |//div[@id="content"]//h4
    |//div[@id="content"]//h5
    |//div[@id="content"]//h6
)

If I run this on this website here (before I answered it), it creates the following listing of tags:

Found 8 elements:
 #00: <h1>
 #01: <h2>
 #02: <h2>
 #03: <h3>
 #04: <h3>
 #05: <h3>
 #06: <h2>
 #07: <h4>

As this demonstrates well, with an xpath query even a list of different elements and with specific conditions like being a child of the div with the id can be created. This code at a glance:

$url = 'http://stackoverflow.com/questions/16307103/use-domdocument-to-replace-all-header-tags-with-the-h4-tags';

$dom = new DOMDocument();
$internalErrorsState = libxml_use_internal_errors(true);
$dom->loadHTMLFile($url);
libxml_use_internal_errors($internalErrorsState);
$xpath = new DOMXPath($dom);

$expression = '
(
    //div[@id="content"]//h1
    |//div[@id="content"]//h2
    |//div[@id="content"]//h3
    |//div[@id="content"]//h4
    |//div[@id="content"]//h5
    |//div[@id="content"]//h6
)';

$elements = $xpath->query($expression);
echo "Found ", $elements->length, " elements:\n";
foreach ($elements as $index => $element) {
    printf(" #%02d: <%s>\n", $index, $element->tagName);
}

Renaming a DOMElement

So what about the second problem, about renaming elements?

DOMDocumet out of the box does not support this. There is a method stub (DOMDocument::renameNode(); undocumented in the current PHP manual) but if you call it you get a warning that it is not implemented:

Warning: DOMDocument::renameNode(): Not yet implemented

Instead one needs to roll her own version. And this is how it works: As you can not rename an element with DOMDocument, all you can do is to create a new element with the renamed name and copy the node to rename all its attributes and children into it and then replace it with the renamed shallow copy. This is done by the following method:

/**
 * Renames a node in a DOM Document.
 *
 * @param DOMElement $node
 * @param string     $name
 *
 * @return DOMNode
 */
function dom_rename_element(DOMElement $node, $name) {
    $renamed = $node->ownerDocument->createElement($name);

    foreach ($node->attributes as $attribute) {
        $renamed->setAttribute($attribute->nodeName, $attribute->nodeValue);
    }

    while ($node->firstChild) {
        $renamed->appendChild($node->firstChild);
    }

    return $node->parentNode->replaceChild($renamed, $node);
}

Bringing this together with the foreach loop from above, next to outputting the tag-names, they can also be renamed:

$elements = $xpath->query($expression);
echo "Found ", $elements->length, " elements:\n";
foreach ($elements as $index => $element) {
    printf(" #%02d: <%s>\n", $index, $element->tagName);
    dom_rename_element($element, 'h4');
    ###################################
}

And then afterwards, querying the xpath expression again, will result in h4 tags only:

$elements = $xpath->query($expression);
echo "Found ", $elements->length, " elements:\n";
foreach ($elements as $index => $element) {
    printf(" #%02d: <%s>\n", $index, $element->tagName);
}

Output:

Found 8 elements:
 #00: <h1>
 #01: <h2>
 #02: <h2>
 #03: <h3>
 #04: <h3>
 #05: <h3>
 #06: <h2>
 #07: <h4>

Full Code-Example

Here the full code-example and its output at a glance:

<?php
/**
 * Use DomDocument to replace all header tags with the h4 tags
 * @link http://stackoverflow.com/q/16307103/367456
 */
$url = 'http://stackoverflow.com/questions/16307103/use-domdocument-to-replace-all-header-tags-with-the-h4-tags';

$dom = new DOMDocument();
$internalErrorsState = libxml_use_internal_errors(true);
$dom->loadHTMLFile($url);
libxml_use_internal_errors($internalErrorsState);
$xpath = new DOMXPath($dom);

$expression = '
(
    //div[@id="content"]//h1
    |//div[@id="content"]//h2
    |//div[@id="content"]//h3
    |//div[@id="content"]//h4
    |//div[@id="content"]//h5
    |//div[@id="content"]//h6
)';

$elements = $xpath->query($expression);
echo "Found ", $elements->length, " elements:\n";
foreach ($elements as $index => $element) {
    printf(" #%02d: <%s>\n", $index, $element->tagName);
    dom_rename_element($element, 'h4');
}

$elements = $xpath->query($expression);
echo "Found ", $elements->length, " elements:\n";
foreach ($elements as $index => $element) {
    printf(" #%02d: <%s>\n", $index, $element->tagName);
}

/**
 * Renames a node in a DOM Document.
 *
 * @param DOMElement $node
 * @param string     $name
 *
 * @return DOMNode
 */
function dom_rename_element(DOMElement $node, $name) {
    $renamed = $node->ownerDocument->createElement($name);

    foreach ($node->attributes as $attribute) {
        $renamed->setAttribute($attribute->nodeName, $attribute->nodeValue);
    }

    while ($node->firstChild) {
        $renamed->appendChild($node->firstChild);
    }

    return $node->parentNode->replaceChild($renamed, $node);
}

If you try it out, you might notice that now, after my answer, the number of heading elements has changed. I hope this is helpful!

这篇关于使用DomDocument替换所有标签标签与h4标签的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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