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

时间:2012-02-23 14:57:58

标签: php xml dom dom-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”获取类似于另一个的名称:

<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代码是什么?有可能吗?

3 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

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

答案 2 :(得分:0)

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

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