dongshi4589 2016-06-14 17:21
浏览 57
已采纳

如何在没有PHP数据的情况下克隆不同的XML结构?

I have an XML document that looks like this:

<root>

  <node/>

  <node>
    <sub>more</sub>
  </node>

  <node>
    <sub>another</sub>
  </node>

  <node>value</node>

</root>

Here's my pseudo-code:

import xml.

create empty-xml.

foreach child of imported-xml-root-node,

    recursively clone node structure without data.

    if clone does not match one already in empty-xml,
        then add clone to empty-xml.

I'm trying to get a result that looks like this:

<root>

  <node/>

  <node>
    <sub/>
  </node>

</root>

Note that my piddly example data is only 3 nodes deep. In production, there will be an unknown number of descendants, so an acceptable answer needs to handle variable node depths.


Failed Approaches

I have reviewed The DOMNode class which has a cloneNode method with a recursive option that I would like to use, although it would take some extra work to purge the data. But while the class contains a hasChildNodes function which returns a boolean, I can't find a way to actually return the collection of children.

$doc = new DOMDocument();
$doc->loadXML($xml);

$root_node = $doc->documentElement;

if ( $root_node->hasChildNodes() ) {

  // looking for something like this:
  // foreach ($root_node->children() as $child)
  //   $doppel = $child->cloneNode(true);

}

Secondly, I have tried my hand with the The SimpleXMLElement class which does have an awesome children method. Although it's lacking the recursive option, I built a simple function to surmount that. But the class is missing a clone/copyNode method, and my function is bloating into something nasty to compensate. Now I'm considering combining usage of the two classes so I've got access to both SimpleXMLElement::children and DOMDocument::cloneNode, but I can tell this is not going cleanly and surely this problem can be solved better.

$sxe = new SimpleXMLElement($xml);

$indentation = 0;

function getNamesRecursive( $xml, &$indentation )
{
    $indentation++;
    foreach($xml->children() as $child) {
        for($i=0;$i<$indentation;$i++)
          echo "\t";
        echo $child->getName() . "
";
        getNamesRecursive($child,$indentation);
    }
    $indentation--;
}

getNamesRecursive($sxe,$indentation);
  • 写回答

2条回答 默认 最新

  • dongzhao1865 2016-06-15 22:02
    关注

    well here's my stinky solution. suggestions for improvements or completely new better answers are still very welcome.

    $xml = '
    <root>
      <node/>
      <node>
        <sub>more</sub>
      </node>
      <node>
        <sub>another</sub>
      </node>
      <node>value</node>
    </root>
    ';
    $doc = new DOMDocument();
    $doc->loadXML($xml);
    
    
    // clone without data
    $empty_xml = new DOMDocument();
    $empty_xml->appendChild($empty_xml->importNode($doc->documentElement));
    function clone_without_data(&$orig, &$clone, &$clonedoc){
      foreach ($orig->childNodes as $child){
        if(get_class($child) === "DOMElement")
          $new_node = $clone->appendChild($clonedoc->importNode($child));
        if($child->hasChildNodes())
          clone_without_data($child,$new_node,$clonedoc);
      }
    }
    clone_without_data($doc->documentElement, $empty_xml->documentElement, $empty_xml);
    
    
    // remove all duplicates
    $distinct_structure = new DOMDocument();
    $distinct_structure->appendChild($distinct_structure->importNode($doc->documentElement));
    foreach ($empty_xml->documentElement->childNodes as $child){
      $match = false;
      foreach ($distinct_structure->documentElement->childNodes as $i => $element){
        if ($distinct_structure->saveXML($element) === $empty_xml->saveXML($child)) {
          $match = true;
          break;
        }
      }
      if (!$match)
        $distinct_structure->documentElement->appendChild($distinct_structure->importNode($child,true));
    }
    $distinct_structure->formatOutput = true;
    echo $distinct_structure->saveXML();
    

    Which results in this output:

    <?xml version="1.0"?>
    <root>
      <node/>
      <node>
        <sub/>
      </node>
    </root>
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 安装svn网络有问题怎么办
  • ¥15 Python爬取指定微博话题下的内容,保存为txt
  • ¥15 vue2登录调用后端接口如何实现
  • ¥65 永磁型步进电机PID算法
  • ¥15 sqlite 附加(attach database)加密数据库时,返回26是什么原因呢?
  • ¥88 找成都本地经验丰富懂小程序开发的技术大咖
  • ¥15 如何处理复杂数据表格的除法运算
  • ¥15 如何用stc8h1k08的片子做485数据透传的功能?(关键词-串口)
  • ¥15 有兄弟姐妹会用word插图功能制作类似citespace的图片吗?
  • ¥15 latex怎么处理论文引理引用参考文献