【问题标题】:php dom Xml loop throught elements preserve childrensphp dom Xml循环遍历元素保留孩子的
【发布时间】:2015-02-11 13:46:17
【问题描述】:

所以我有一个像这样的 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>

所以它削减了&lt;photos&gt; 的所有孩子,所以我的问题是如何保护孩子并将孩子的标签从&lt;img&gt; 更改为&lt;photo&gt;

【问题讨论】:

    标签: php xml dom children


    【解决方案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

    【讨论】:

    • 感谢您的回答,但我认为您不明白我想做什么。我不能改变我的代码,因为我需要改变我所有的项目。我只需要在我现有的代码中添加两个字符串来解决我的问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多