php dom Xml 遍历元素保留子元素

php dom Xml loop throught elements preserve childrens

所以我有一个 Xml 文件,例如

<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>

所以我需要将所有标签名称更改为替代名称,我需要得到类似

的东西
<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. getElementByTagName() 和 $childNodes return 'live' 列表,如果您更改 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。 PHP 支持 XSLT ext/xsl.