此代码仅附加5个名称节点中的3个。这是为什么? 这是原始的XML: 它有5个名称节点。
<?xml version='1.0'?>
<products>
<product>
<itemId>531670</itemId>
<modelNumber>METRA ELECTRONICS/MOBILE AUDIO</modelNumber>
<categoryPath>
<category><name>Buy</name></category>
<category><name>Car, Marine & GPS</name></category>
<category><name>Car Installation Parts</name></category>
<category><name>Deck Installation Parts</name></category>
<category><name>Antennas & Adapters</name></category>
</categoryPath>
</product>
</products>
然后运行这个PHP代码。这被假定为将所有名称节点附加到产品节点中。
<?php
// load up your XML
$xml = new DOMDocument;
$xml->load('book.xml');
// Find all elements you want to replace. Since your data is really simple,
// you can do this without much ado. Otherwise you could read up on XPath.
// See http://www.php.net/manual/en/class.domxpath.php
//$elements = $xml->getElementsByTagName('category');
// WARNING: $elements is a "live" list -- it's going to reflect the structure
// of the document even as we are modifying it! For this reason, it's
// important to write the loop in a way that makes it work correctly in the
// presence of such "live updates".
foreach ($xml->getElementsByTagName('product') as $product ) {
foreach($product->getElementsByTagName('name') as $name ) {
$product->appendChild($name );
}
$product->removeChild($xml->getElementsByTagName('categoryPath')->item(0));
}
// final result:
$result = $xml->saveXML();
echo $result;
?>
最终结果是这个,它只附加3个名称节点:
<?xml version="1.0"?>
<products>
<product>
<itemId>531670</itemId>
<modelNumber>METRA ELECTRONICS/MOBILE AUDIO</modelNumber>
<name>Buy</name>
<name>Antennas & Adapters</name>
<name>Car Installation Parts</name>
</product>
</products>
为什么只附加3个名称节点?
答案 0 :(得分:1)
当您从中提取结果时,您正在修改DOM树。对树的任何修改都会覆盖先前查询操作的结果(您的getElementsByTagName)使这些结果无效,因此您将获得未定义的结果。对于添加/删除节点的操作尤其如此。
答案 1 :(得分:1)
当您迭代它们时,您正在移动节点,因此会跳过2个节点。我不是一个php人,所以我不能给你代码来做这个,但你需要做的是建立一个名称节点的集合,并反过来遍历该集合。
答案 2 :(得分:1)
您可以在附加之前临时将name
元素添加到数组中,因为您实时修改了DOM。 getElementsByTagName()
生成的节点列表可能会随着您移动节点而改变(实际上这似乎正在发生)。
<?php
// load up your XML
$xml = new DOMDocument;
$xml->load('book.xml');
// Array to store them
$append = array();
foreach ($xml->getElementsByTagName('product') as $product ) {
foreach($product->getElementsByTagName('name') as $name ) {
// Stick $name onto the array
$append[] = $name;
}
// Now append all of them to product
foreach ($append as $a) {
$product->appendChild($a);
}
$product->removeChild($xml->getElementsByTagName('categoryPath')->item(0));
}
// final result:
$result = $xml->saveXML();
echo $result;
?>
输出,附加所有值:
<?xml version="1.0"?>
<products>
<product>
<ItemId>531670</ItemId>
<modelNumber>METRA ELECTRONICS/MOBILE AUDIO</modelNumber>
<name>Buy</name><name>Car, Marine & GPS</name><name>Car Installation Parts</name><name>Deck Installation Parts</name><name>Antennas & Adapters</name></product>
</products>
答案 3 :(得分:0)
一种不太复杂的方法是使用insertBefore
操作节点foreach($xml->getElementsByTagName('name') as $node){
$gp = $node->parentNode->parentNode;
$ggp = $gp->parentNode;
// move the node above gp without removing gp or parent
$ggp->insertBefore($node,$gp);
}
// remove the empty categoryPath node
$ggp->removeChild($gp);