2015-02-11 41 views
0

所以我有这样PHP DOM的Xml循环throught元素保持儿童

<cars> 
    <id>1</id> 
    <photos> 
     <img>http://sit.com/img.jpg</img> 
     <img>http://sit.com/img.jpg</img> 
     <img>http://sit.com/img.jpg</img> 
     <img>http://sit.com/img.jpg</img> 
    </photos> 
</cars> 

一个XML文件,所以我需要所有的标签名称更改为替代,我需要得到像

<cars> 
    <ex_id>1</ex_id> 
    <images> 
     <photo>http://sit.com/img.jpg</photo> 
     <photo>http://sit.com/img.jpg</photo> 
     <photo>http://sit.com/img.jpg</photo> 
     <photo>http://sit.com/img.jpg</photo> 
    </images> 
</cars> 

我的代码是

foreach ($dom->getElementsByTagName('cars') as $item) { 
    for ($i = 0; $i < $item->childNodes->length; ++$i) { 
     $car = $item->childNodes->item($i); 
     $NewElement = $dom->createElement($newName,$value); 
     $car->parentNode->replaceChild($NewElement->cloneNode(TRUE), $car); 
    } 
} 

做这样的事情

<cars> 
    <ex_id>1</ex_id> 
    <images/> 
</cars> 

所以切<photos>所有儿童,所以我的问题是如何保护孩子,改变儿童的标签从<img><photo>

回答

1

这里有几个问题:

  1. getElementByTagName()和$ childNodes返回“实时”列表,如果您更改DOM,它们会更改。你可以使用iterator_to_array()将它们复制到一个数组中。

  2. 这里不仅是元素节点。注释,cdata部分和文本(甚至只包含空格)也是节点。如果迭代$ childNodes,则必须验证DOMNode :: $ nodeType。

  3. 请勿使用DOMDocument :: createElement()的第二个参数。它有一个突破逃脱。创建一个文本节点并追加它。

如果您使用Xpath来获取节点,则1和2会消失。

$dom = new DOMDocument(); 
$dom->loadXml($xml); 
$xpath = new DOMXPath($dom); 

foreach ($xpath->evaluate('/cars/images/img') as $photo) { 
    $newNode = $dom->createElement('photo'); 
    $newNode->appendChild($dom->createTextNode($photo->textContent)); 
    $photo->parentNode->replaceChild($newNode, $photo); 
} 

echo $dom->saveXml(); 

输出:

<?xml version="1.0"?> 
<cars> 
    <ex_id>1</ex_id> 
    <images> 
     <photo>http://sit.com/img.jpg</photo> 
     <photo>http://sit.com/img.jpg</photo> 
     <photo>http://sit.com/img.jpg</photo> 
     <photo>http://sit.com/img.jpg</photo> 
    </images> 
</cars> 

改变一个DOM文档往往是一个坏主意。这是比较容易从源文件提取数据,并建立一个新的目标文档:

$source = new DOMDocument(); 
$source->loadXml($xml); 
$xpath = new DOMXPath($source); 

$target = new DOMDocument(); 
$target->formatOutput = TRUE; 

$cars = $target->appendChild($target->createElement('cars')); 
$cars 
    ->appendChild($target->createElement('ex_id')) 
    ->appendChild(
     $target->createTextNode(
     $xpath->evaluate('string(/cars/id)') 
    ) 
    ); 

$images = $cars->appendChild($target->createElement('images')); 

foreach ($xpath->evaluate('/cars/photos/img') as $photo) { 
    $images 
    ->appendChild($target->createElement('photo')) 
    ->appendChild($target->createTextNode($photo->textContent)); 
} 

echo $target->saveXml(); 

输出:

<?xml version="1.0"?> 
<cars> 
    <ex_id>1</ex_id> 
    <images> 
    <photo>http://sit.com/img.jpg</photo> 
    <photo>http://sit.com/img.jpg</photo> 
    <photo>http://sit.com/img.jpg</photo> 
    <photo>http://sit.com/img.jpg</photo> 
    </images> 
</cars> 

这里是一个致力于将XML语言 - XSLT。 XSLT由PHP ext/xsl支持。

+0

感谢您的回答,但我认为你不明白我想要做什么。我不能改变我的代码,因为那时我需要改变我的所有项目。我只需要添加两个字符串到我现有的代码来解决我的问题 – 2015-02-11 14:21:15