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


PHP - DOM - XML - Nodes with similar attribute manipulation

我必须使用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>

我想对读取<node1>中"name"属性的所有节点进行分组,以获得与另一个"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>

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

您可以这样做(请确保您的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;
    }
}

您可以使用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

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

注意,我假设根节点是<nodes>