我需要将子节点附加到其父节点,但父节点应为div
。
我需要检查,如果父节点不是div
,那么检查父节点,直到我得到div节点。怎么做?
XML文件
<div class="parent">
<div class="boxed-text">box text1</div>
<li>
<div class="boxed-text">box text2</div>
<p>para</p>
</li>
<div class="boxed-text">box text3</div>
<p>para</p>
</div>
预期输出(应附加到div父节点)
<div class="parent">
<li>
<p>para</p>
</li>
<p>para</p>
<div class="boxed-text">box text1</div>
<div class="boxed-text">box text2</div>
<div class="boxed-text">box text3</div>
</div>
但是我得到了如下输出:(即盒装文本2的父节点是li
标签,所以它被附加到那里而不是div父节点。如何只获得div父节点来附加子节点节点?)
<div class="parent">
<li>
<p>para</p>
<div class="boxed-text">box text2</div>
</li>
<p>para</p>
<div class="boxed-text">box text1</div>
<div class="boxed-text">box text3</div>
</div>
我的代码:
$dom = new DOMDocument;
$dom->load("new_test.xml", LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$xp = new DOMXPath($dom);
$xp->registerNamespace("php", "http://php.net/xpath");
$div = $xp->query("//div[@class='boxed-text']");
foreach($div as $divv) {
$divv->parentNode->appendChild($divv);
}
$r = $dom->saveXML();
答案 0 :(得分:1)
您将节点附加到其父节点,但这只会将它们移动到父节点内的最后位置 - 它不会更改父节点。
Xpath有一个轴的概念。默认轴为child
- 当前上下文的子项。但是这里有几个其他的,包括ancestor
,它代表了返回文档根目录的路径。
$dom = new DOMDocument;
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
$dom->load("new_test.xml", LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$xp = new DOMXPath($dom);
$xp->registerNamespace("php", "http://php.net/xpath");
$divs = $xp->evaluate("//div[@class='boxed-text']");
foreach($divs as $div) {
$ancestor = $xp->evaluate('ancestor::div[1]', $div)->item(0);
if ($ancestor) {
$ancestor->appendChild($div);
}
}
echo $dom->saveXML();
输出:
<?xml version="1.0"?>
<div class="parent">
<li>
<p>para</p>
</li>
<p>para</p>
<div class="boxed-text">box text1</div>
<div class="boxed-text">box text2</div>
<div class="boxed-text">box text3</div>
</div>
另一种方法是遍历父div元素并为每个元素获取盒装文本后代:
$parents = $xp->evaluate("//div[.//div[@class='boxed-text']]");
foreach ($parents as $parent) {
foreach ($xp->evaluate(".//div[@class='boxed-text']", $parent) as $text) {
$parent->appendChild($text);
}
}
答案 1 :(得分:0)
下面的代码未经过测试,但我会使用XPath显式获取父节点,而不是使用当前的parentNode方法,并在第一个循环中从dom中删除div元素,然后在最后添加它们
$tmp=array();
$dom = new DOMDocument;
$dom->load( "new_test.xml", LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD );
$xp = new DOMXPath( $dom );
$xp->registerNamespace("php", "http://php.net/xpath");
/* Find the parent based on it's class */
$parent=$xp->query("//div[class='parent']")->item(0);
/* Find the nodes of interest and remove - store in temp array */
$col = $xp->query("//div[@class='boxed-text']");
foreach( $col as $node ) $tmp[]=$parent->removeChild( $node );
/* Add the nodes back at the end */
foreach( $tmp as $node ) $parent->appendChild( $node );
$r = $dom->saveXML();