Php 递归解析XML文档
我有包含文章信息的XML文档,它们有一种层次结构:Php 递归解析XML文档,php,xml,recursion,xml-parsing,domdocument,Php,Xml,Recursion,Xml Parsing,Domdocument,我有包含文章信息的XML文档,它们有一种层次结构: <?xml version="1.0" encoding="UTF-8"?> <page> <elements> <element> <type>article</type> <id>1</id> <parentContainerID>page</parentContainerID> <parentContainer
<?xml version="1.0" encoding="UTF-8"?>
<page>
<elements>
<element>
<type>article</type>
<id>1</id>
<parentContainerID>page</parentContainerID>
<parentContainerType>page</parentContainerType>
</element>
<element>
<type>article</type>
<id>2</id>
<parentContainerID>1</parentContainerID>
<parentContainerType>article</parentContainerType>
</element>
<element>
<type>photo</type>
<id>3</id>
<parentContainerID>2</parentContainerID>
<parentContainerType>article</parentContainerType>
</element>
<... more elements ..>
</elements>
</page>
文章
1.
页
页
文章
2.
1.
文章
照片
3.
2.
文章
元素具有节点parentContainerID和节点parentContainerType。如果parentContainerType==page,则这是主元素。parentContainerID显示元素的主元素。因此它应该是这样的:1在XML中没有嵌套/递归。
节点是同级节点。为了构建父子关系,我建议在XML上循环并构建两个数组。一个用于关系,一个用于引用元素
$xml = file_get_contents('php://stdin');
$document = new DOMDocument();
$document->loadXml($xml);
$xpath = new DOMXpath($document);
$relations = [];
$elements = [];
foreach ($xpath->evaluate('//element') as $element) {
$id = (int)$xpath->evaluate('string(id)', $element);
$parentId = (int)$xpath->evaluate('string(parentContainerID)', $element);
$relations[$parentId][] = $id;
$elements[$id] = $element;
}
var_dump($relations);
输出:
array(3) {
[0]=>
array(1) {
[0]=>
int(1)
}
[1]=>
array(1) {
[0]=>
int(2)
}
[2]=>
array(1) {
[0]=>
int(3)
}
}
1: article
2: article
3: photo
关系数组现在包含任何父元素的子ID,没有父元素的元素位于索引0中。这允许您使用递归函数以树的形式访问元素
function traverse(
int $parentId, callable $callback, array $elements, array $relations, $level = -1
) {
if ($elements[$parentId]) {
$callback($elements[$parentId], $parentId, $level);
}
if (isset($relations[$parentId]) && is_array($relations[$parentId])) {
foreach ($relations[$parentId] as $childId) {
traverse($childId, $callback, $elements, $relations, ++$level);
}
}
}
这将对每个节点执行回调。正确的实现方法是使用递归迭代器
,但函数应该用于示例
traverse(
0,
function(DOMNode $element, int $id, int $level) use ($xpath) {
echo str_repeat(' ', $level);
echo $id, ": ", $xpath->evaluate('string(type)', $element), "\n";
},
$elements,
$relations
);
输出:
array(3) {
[0]=>
array(1) {
[0]=>
int(1)
}
[1]=>
array(1) {
[0]=>
int(2)
}
[2]=>
array(1) {
[0]=>
int(3)
}
}
1: article
2: article
3: photo
请注意,
$xpath
对象作为回调的上下文提供。由于$elements
数组包含原始节点,因此可以使用Xpath表达式从与当前元素节点相关的DOM中获取详细数据。“现在我需要构建一个新的页面(html),该页面包含如下内容:ID 1的内容、ID 2的内容、ID 3的内容”-只是顺序的或嵌套的,根据XML定义的父/子关系?如果不是嵌套的,为什么要在这里使用递归?XML中的元素也不是嵌套的,它们都在同一级别上。我可能会先把这些东西读入数组,然后对它们进行相应的排序。。。然后根据父/子关系对其进行循环以生成所需的output.CBroe。