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