php dom Xml循环通过元素保存孩子们的

时间:2015-02-11 13:46:17

标签: php xml dom children

所以我有一个像

这样的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 个答案:

答案 0 :(得分:1)

以下是几个问题:

  1. getElementByTagName()和$ childNodes返回&#39; live&#39;列表,如果您更改DOM,它们会更改。您可以使用iterator_to_array()将它们复制到数组中。

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

  3. 不要使用DOMDocument :: createElement()的第二个参数。它有一个破碎的逃脱。创建一个文本节点并附加它。

  4. 如果使用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 ext/xsl支持XSLT。