【问题标题】:PHP - DOM - XML - Nodes with similar attribute manipulationPHP - DOM - XML - 具有相似属性操作的节点
【发布时间】:2012-03-14 00:00:08
【问题描述】:

我必须使用 DOM 操作 XML 文件

这是我的情况:

<mainnode>
<node1  name="aaa">
           <subnode   name="123456" />
    </node1>

    <node1  name="bbb">
           <subnode   name="28472" />
    </node1>

    <node1  name="aaa">
           <subnode   name="92328" />
    </node1>

    <node1  name="ccc">
           <subnode   name="53554" />
    </node1>

    <node1  name="ccc">
           <subnode   name="01928" />
    </node1>

    <node1  name="aaa">
           <subnode   name="39576" />
    </node1>

    <node1  name="ddd">
           <subnode   name="66666" />
    </node1>
</mainnode>

我想将读取&lt;node1&gt;中“名称”属性的所有节点分组,以便为​​每个等于另一个“名称”的“名称”获得类似的东西:

<mainnode>    
<node1 name="aaa">
          <subnode   name="123456" />
          <subnode   name="92328" />
          <subnode   name="39576" />
    </node1>


    <node1  name="bbb">
          <subnode   name="28472" />
    </node1>

    <node1  name="ccc">
          <subnode   name="53554" />
          <subnode   name="01928" />
     </node1>

    <node1  name="ddd">
          <subnode   name="66666" />
    </node1>
</mainnode>

用 dom 进行这种操作的 php 代码是什么?有可能吗?

【问题讨论】:

  • 有可能吗? 是的。进行这种操作的 php 代码是什么? php.net/manual/en/book.dom.php 。你试过什么?
  • XML 没有根节点
  • @gordon:添加了根节点,顺便说一句,我的代码只是为了举例
  • 它仍然无效。子节点应为&lt;subnode/&gt; 或关闭&lt;/subnode&gt;。即使它只是一个例子。如果您提供无效的 xml,那么您就是在为想要提供帮助的人增加障碍。
  • @rdlowrey 我尝试通过使用 getElementsByTagName 读取属性来读取节点,但我无法对所有不同的节点进行分组

标签: php xml dom dom-manipulation


【解决方案1】:

假设$xml 持有您的 XML 字符串 (demo):

$dom = new DOMDocument;
$dom->preserveWhiteSpace = false;
$dom->loadXML($xml);
$xpath = new DOMXPath($dom);
// iterate all the subnodes
foreach ($xpath->query('/nodes/node1/subnode') as $subnode) {
    // get the subnodes parent node's name attribute
    $name = $subnode->parentNode->getAttribute('name');
    // fetch the first node element with that name attribute
    $node = $xpath->query("/nodes/node1[@name='$name']")->item(0);
    // move the subnode there
    $node->appendChild($subnode);
}
// iterate over all node1 elements that are now empty
foreach($xpath->query('/nodes/node1[not(*)]') as $node) {
    // remove them
    $node->parentNode->removeChild($node);
}
// print new dom tree
$dom->formatOutput = true;
echo $dom->saveXML();

请注意,我假设根节点为&lt;nodes&gt;

【讨论】:

    【解决方案2】:

    你可以这样做(请确保你的XML之前是规范化的):

    // load the xml and prepare the dom
    $dom = new DOMDocument('1.0', 'UTF-8');
    
    // do not display parsing errors to the user
    libxml_use_internal_errors(true)
    
    // load xml
    $dom->loadXML($string);
    
    // optionally handle parsing errors provided in libxml_get_errors()
    
    // store the node names
    $nodeNames = array();
    
    // get all nodes
    $nodes = $dom->getElementsByTagName('node1');
    
    
    foreach ($nodes as $node)
    {
        /* @var $node DOMElement */
        $nodeName = $node->getAttribute("name");
    
        if (isset($nodeNames[$nodeName]))
        {
            /* @var $previousNode DOMElement */
            $previousNode = $nodeNames[$nodeName];
    
            if ($node->hasChildNodes())
            {
                foreach ($node->childNodes as $childNode)
                {
                    $previousNode->appendChild($childNode);
                }
            }
    
            $node->parentNode->removeChild($node);
        }
        else
        {
            $nodeNames[$nodeName] = $node;
        }
    }
    

    【讨论】:

    • 抑制解析错误的正确方法是使用libxml_use_internal_errors(true)
    • @ Gordon 我将其添加到我的答案中。 @ 运算符只是一个肮脏的黑客,看看示例代码是否真的有效。谢谢!
    【解决方案3】:

    您可以使用 PHP XQuery 扩展来执行此操作:

    let $data := (: your xml :)
    return
        element mainnode {
            for $nodes in $data/node1
            let $name := string($nodes/@name) 
            group by $name 
            return
             element {$name} {
                 attribute name {$name},
                for $node in $nodes
                return $node/subnode 
            }
        }
    

    您可以在http://www.zorba-xquery.com/html/demo#TuRqsG1GZewGQD3f0QhmsIpVmTc= 现场试用该示例 有关如何在 PHP 上安装 XQuery 扩展的说明,请访问 http://www.zorba-xquery.com/html/entry/2011/12/27/PHP_Meets_XQuery

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-29
      • 2015-05-18
      • 2019-05-29
      • 1970-01-01
      相关资源
      最近更新 更多