Php 使用递归迭代XML文件

Php 使用递归迭代XML文件,php,xml,recursion,Php,Xml,Recursion,我在尝试处理一个递归函数时遇到了问题。我有一个XML文件,它基本上记录了一个文件/文件夹结构。这些XML节点(代表一个文件/文件夹)可以是N个深度。因此,我正在尝试编写一个脚本,在所有节点上进行迭代,并在数据库中创建条目。对于文件夹,我有一个表结构,其中包含ID、field\u name和parent\u ID列。父文件夹id指向当前文件夹所在文件夹的id。如果在根级别,则ID为0 我的问题是,我不能准确地跟踪父母的id,当我的爱人水平下降,然后回来。下面是一个XML示例,但请注意文件夹可以是任

我在尝试处理一个递归函数时遇到了问题。我有一个XML文件,它基本上记录了一个文件/文件夹结构。这些XML节点(代表一个文件/文件夹)可以是N个深度。因此,我正在尝试编写一个脚本,在所有节点上进行迭代,并在数据库中创建条目。对于文件夹,我有一个表结构,其中包含ID、field\u name和parent\u ID列。父文件夹id指向当前文件夹所在文件夹的id。如果在根级别,则ID为0

我的问题是,我不能准确地跟踪父母的id,当我的爱人水平下降,然后回来。下面是一个XML示例,但请注意文件夹可以是任意级别:

<XML>
    <programs>
        <program name ="xxx">
            <groups>
                <group id ="1" name ="yyy">
                    <folder name = "ggg">
                        <file name = "ddfdf"/>
                        <file name = "ddfdf"/>
                        <folder name = "sub" />
                    </folder>
                    <folder name = "sdfsdfs">
                        <file name = "ddfdf"/>                  
                        <folder name = "sub" >
                            <file name = "ddfdf"/>
                        </folder>       
                    </folder>
                </group>
            </groups>
        </program>
    </programs>
</xml>

这不是一个完整的解决方案,但它展示了如何使用递归迭代器来完成您想要做的事情

    $strxml='
    <xml>
        <programs>
            <program name ="xxx">
                <groups>
                    <group id ="1" name ="yyy">
                        <folder name = "ggg">
                            <file name = "ddfdf"/>
                            <file name = "ddfdf"/>
                            <folder name = "sub" />
                        </folder>
                        <folder name = "sdfsdfs">
                            <file name = "ddfdf"/>                  
                            <folder name = "sub" >
                                <file name = "ddfdf"/>
                            </folder>       
                        </folder>
                    </group>
                </groups>
            </program>
        </programs>
    </xml>';

    class RecursiveDOMIterator implements RecursiveIterator {
        private $index;
        private $list;

        public function __construct(DOMNode $domNode){
            $this->index = 0;
            $this->list = $domNode->childNodes;
        }
        public function current(){
            return $this->list->item($this->index);
        }
        public function getChildren(){
            return new self( $this->current() );
        }
        public function hasChildren(){
            return $this->current()->hasChildNodes();
        }
        public function key(){
            return $this->index;
        }
        public function next(){
            $this->index++;
        }
        public function rewind(){
            $this->index = 0;
        }
        public function valid(){
            return $this->index < $this->list->length;
        }
    }



    $xml=new DOMDocument;
    $xml->loadXML( $strxml );
    $rootnode=$xml->getElementsByTagName('programs')->item(0);

    $nodeItr=new RecursiveDOMIterator( $rootnode );
    $itr=new RecursiveIteratorIterator( $nodeItr, RecursiveIteratorIterator::SELF_FIRST );
    foreach( $itr as $node ) {
        if( $node->nodeType === XML_ELEMENT_NODE ) {
            $id=$node->hasAttribute('id') ? $node->getAttribute('id') : false;
            $attr=$node->hasAttribute('name') ? $node->getAttribute('name') : false;
            echo $id.' '.$node->nodeName . ' ' . $node->nodeValue. ' ' . $attr .' '.$node->parentNode->tagName . ' ' . '<br />';
        }
    }
    $dom=$rootnode=$itr=$nodeItr=null;
$strxml='1!'
';
类递归迭代器实现递归迭代器{
私人美元指数;
私人名单;
公共函数构造(DOMNode$DOMNode){
$this->index=0;
$this->list=$domNode->childNodes;
}
公共职能(当前){
返回$this->list->item($this->index);
}
公共函数getChildren(){
返回新的自我($this->current());
}
公共职能(儿童){
返回$this->current()->hasChildNodes();
}
公共函数密钥(){
返回$this->index;
}
公共职能下一步(){
$this->index++;
}
公共函数倒带(){
$this->index=0;
}
公共函数有效(){
返回$this->index<$this->list->length;
}
}
$xml=新文档;
$xml->loadXML($strxml);
$rootnode=$xml->getElementsByTagName('programs')->item(0);
$nodeItr=新的递归多米塔尔($rootnode);
$itr=新的递归迭代器($nodeItr,递归迭代器::SELF_FIRST);
foreach($itr作为$node){
if($node->nodeType===XML\u元素\u节点){
$id=$node->hasAttribute('id')?$node->getAttribute('id'):false;
$attr=$node->hasAttribute('name')?$node->getAttribute('name'):false;
回显$id'.$node->nodeName'.$node->nodeValue'.$attr'.$node->parentNode->tagName'.'.
; } } $dom=$rootnode=$itr=$nodeItr=null;
这不是一个完整的解决方案,但它展示了如何使用递归迭代器来完成您想要做的事情

    $strxml='
    <xml>
        <programs>
            <program name ="xxx">
                <groups>
                    <group id ="1" name ="yyy">
                        <folder name = "ggg">
                            <file name = "ddfdf"/>
                            <file name = "ddfdf"/>
                            <folder name = "sub" />
                        </folder>
                        <folder name = "sdfsdfs">
                            <file name = "ddfdf"/>                  
                            <folder name = "sub" >
                                <file name = "ddfdf"/>
                            </folder>       
                        </folder>
                    </group>
                </groups>
            </program>
        </programs>
    </xml>';

    class RecursiveDOMIterator implements RecursiveIterator {
        private $index;
        private $list;

        public function __construct(DOMNode $domNode){
            $this->index = 0;
            $this->list = $domNode->childNodes;
        }
        public function current(){
            return $this->list->item($this->index);
        }
        public function getChildren(){
            return new self( $this->current() );
        }
        public function hasChildren(){
            return $this->current()->hasChildNodes();
        }
        public function key(){
            return $this->index;
        }
        public function next(){
            $this->index++;
        }
        public function rewind(){
            $this->index = 0;
        }
        public function valid(){
            return $this->index < $this->list->length;
        }
    }



    $xml=new DOMDocument;
    $xml->loadXML( $strxml );
    $rootnode=$xml->getElementsByTagName('programs')->item(0);

    $nodeItr=new RecursiveDOMIterator( $rootnode );
    $itr=new RecursiveIteratorIterator( $nodeItr, RecursiveIteratorIterator::SELF_FIRST );
    foreach( $itr as $node ) {
        if( $node->nodeType === XML_ELEMENT_NODE ) {
            $id=$node->hasAttribute('id') ? $node->getAttribute('id') : false;
            $attr=$node->hasAttribute('name') ? $node->getAttribute('name') : false;
            echo $id.' '.$node->nodeName . ' ' . $node->nodeValue. ' ' . $attr .' '.$node->parentNode->tagName . ' ' . '<br />';
        }
    }
    $dom=$rootnode=$itr=$nodeItr=null;
$strxml='1!'
';
类递归迭代器实现递归迭代器{
私人美元指数;
私人名单;
公共函数构造(DOMNode$DOMNode){
$this->index=0;
$this->list=$domNode->childNodes;
}
公共职能(当前){
返回$this->list->item($this->index);
}
公共函数getChildren(){
返回新的自我($this->current());
}
公共职能(儿童){
返回$this->current()->hasChildNodes();
}
公共函数密钥(){
返回$this->index;
}
公共职能下一步(){
$this->index++;
}
公共函数倒带(){
$this->index=0;
}
公共函数有效(){
返回$this->index<$this->list->length;
}
}
$xml=新文档;
$xml->loadXML($strxml);
$rootnode=$xml->getElementsByTagName('programs')->item(0);
$nodeItr=新的递归多米塔尔($rootnode);
$itr=新的递归迭代器($nodeItr,递归迭代器::SELF_FIRST);
foreach($itr作为$node){
if($node->nodeType===XML\u元素\u节点){
$id=$node->hasAttribute('id')?$node->getAttribute('id'):false;
$attr=$node->hasAttribute('name')?$node->getAttribute('name'):false;
回显$id'.$node->nodeName'.$node->nodeValue'.$attr'.$node->parentNode->tagName'.'.
; } } $dom=$rootnode=$itr=$nodeItr=null;
考虑使用XSLT将XML简化为一个子级格式。然后运行一个简单的PHP循环来提取父id和文件夹数据以进行数据库迁移。事实上,如果使用MySQL,您可以将这个经过精确转换的XML文档导入到数据库中,那么节点名称应该与列名匹配

作为信息,是一种特殊用途的声明性编程语言(与SQL类型相同),用于将XML文档重新构造为各种结构,以满足最终使用需求。与所有通用语言(包括C#、Java、Python、Perl、VB)一样,PHP维护一个XSLT处理器。下面是XSLT脚本(您可以为XML文档中的每个嵌套添加XSLT)和PHP脚本(用于转换和迭代输出)

XSLT脚本(另存为.xsl或.XSLT)


0
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>

  <xsl:template match="/">
    <root>
      <xsl:apply-templates select="*"/>
    </root>
  </xsl:template>  

  <xsl:template match="folder" name="foldertemplate">
    <row>      
      <parent_id>0</parent_id>      
      <field_name><xsl:value-of select="@name"/></field_name>      
    </row>

    <!-- ADD LEVELS FOR EACH NEST IN XML DOCUMENT -->
    <row>
      <parent_id><xsl:value-of select="@name"/></parent_id>      
      <field_name><xsl:value-of select="folder/@name"/></field_name>      
    </row>

    <!-- EXAMPLE NEXT LEVEL -->
    <!-- <row> -->
    <!--   <parent_id><xsl:value-of select="folder/@name"/></parent_id> -->      
    <!--   <field_name><xsl:value-of select="folder/folder/@name"/></field_name> -->    
    <!-- </row> -->
  </xsl:template>

</xsl:transform>
<?xml version="1.0" encoding="UTF-8"?>
<root>
  <row>
    <parent_id>0</parent_id>
    <field_name>ggg</field_name>
  </row>
  <row>
    <parent_id>ggg</parent_id>
    <field_name>sub</field_name>
  </row>
  <row>
    <parent_id>0</parent_id>
    <field_name>sdfsdfs</field_name>
  </row>
  <row>
    <parent_id>sdfsdfs</parent_id>
    <field_name>sub</field_name>
  </row>
</root>
// Set current directory
$cd = dirname(__FILE__);

// Load the XML source and XSLT file
$doc = new DOMDocument();
$doc->load($cd.'/Input.xml');

$xsl = new DOMDocument;
$xsl->load($cd.'/XSLTScript.xsl');

// Configure the transformer
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl); 

// Transform XML source
$newXml = $proc->transformToXML($doc);

// Save output to file
$xmlfile = $cd.'/Output.xml';
file_put_contents($xmlfile, $newXml);    

// Load new XML with SimpleXML
$newdoc = simplexml_load_file($cd.'/Output.xml');

$data = [];
$node = $newdoc->xpath('//row');
$parents = $newdoc->xpath('//row/parent_id');
$folders = $newdoc->xpath('//row/field_name');    

// Loop through folder names and parent
for($i=0; $i < sizeof($node); $i++) {        
    echo 'parent: '.$parents[$i]. ' folder: ' . $folders[$i]."\n";    
}

#parent: 0 folder: ggg
#parent: ggg folder: sub
#parent: 0 folder: sdfsdfs
#parent: sdfsdfs folder: sub