简体   繁体   English

PHP - DOM - XML - 具有类似属性操作的节点

[英]PHP - DOM - XML - Nodes with similar attribute manipulation

I have to manipulate a XML file with DOM 我必须使用DOM操作XML文件

This is my situation: 这是我的情况:

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

And I want to group all my nodes reading the "name" attribute in <node1> to obtain something like this for every "name" equal to another one: 我想将所有节点分组读取<node1>的“name”属性,为每个“name”获取类似于另一个的名称:

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

What is the php code to do this kind of manipulation with dom? 用dom做这种操作的php代码是什么? is it possible? 可能吗?

You can do it like this (please ensure that your XML is normalized before): 您可以这样做(请确保您的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;
    }
}

You can use the PHP XQuery extension in order to do this: 您可以使用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 
        }
    }

You can try the example live at http://www.zorba-xquery.com/html/demo#TuRqsG1GZewGQD3f0QhmsIpVmTc= Instructions on how to install the XQuery extension on PHP is available at http://www.zorba-xquery.com/html/entry/2011/12/27/PHP_Meets_XQuery 您可以在http://www.zorba-xquery.com/html/demo#TuRqsG1GZewGQD3f0QhmsIpVmTc查看示例有关如何在PHP上安装XQuery扩展的说明,请访问http://www.zorba-xquery.com/ HTML /项/ 2011/12月27日/ PHP_Meets_XQuery

Assuming $xml holds your XML string ( demo ): 假设$xml保存您的XML字符串( 演示 ):

$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();

Note that I am assuming the root node to be <nodes> . 请注意,我假设根节点是<nodes>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM