简介
我想循环使用灵活的类别结构的XML文件。
问题:
我不知道循环理论的infinte子类别而不必为每个“语句”制作x量(参见底部的编码示例)。如何动态遍历类别结构?
<?xml version="1.0" encoding="utf-8"?>
<catalog>
<category name="Category - level 1">
<category name="Category - level 2" />
<category name="Category - level 2">
<category name="Category - level 3" />
</category>
<category name="Category - level 2">
<category name="Category - level 3">
<category name="Category - level 4" />
</category>
</category>
</category>
</catalog>
我现在拥有的内容:
使用set结构循环遍历XML文件没有问题:
<catalog>
<category name="Category - level 1">
<category name="Category - level 2">
<category name="Category - level 3" />
</category>
<category name="Category - level 2">
<category name="Category - level 3" />
</category>
</category>
</catalog>
编码示例:
//$xml holds the XML file
foreach ( $xml AS $category_level1 )
{
echo $category_level1['name'];
foreach ( $category_level1->category AS $category_level2 )
{
echo $category_level2['name'];
foreach ( $category_level2->category AS $category_level3 )
{
echo $category_level3['name'];
}
}
}
答案 0 :(得分:6)
通过XPath获取类别中的名称属性可能是最快的,例如
$categoryNames = $doc->xpath('//category/@name');
但是,如果要递归迭代任意嵌套的XML结构,还可以使用SimpleXMLIterator,例如{0}}。 $xml
是您提供的字符串:
$sxi = new RecursiveIteratorIterator(
new SimpleXMLIterator($xml),
RecursiveIteratorIterator::SELF_FIRST);
foreach($sxi as $node) {
echo str_repeat("\t", $sxi->getDepth()), // indenting
$node['name'], // getting attribute name
PHP_EOL; // line break
}
将给出
Category - level 1
Category - level 2
Category - level 2
Category - level 3
Category - level 2
Category - level 3
Category - level 4
就像开头所说的那样,当只想获取所有名称属性时,使用XPath,因为遍历每个节点都很慢。仅当您想要对节点执行更复杂的操作时才使用此方法,例如向其添加内容。
答案 1 :(得分:2)
<?php
$xml= new SimpleXMLElement('.....');
foreach ($xml->xpath('//category') as $cat)
{
echo $cat['name'];
}
答案 2 :(得分:1)
一种可能的解决方案是编写recursive function,即:
这种解决方案的一个优点是,您可以在XML文档中跟踪当前的深度 - 如果您需要将数据表示为树,则可能非常有用实例
例如,如果您的XML加载如下:
$string = <<<XML
<catalog>
<category name="Category - level 1">
<category name="Category - level 2">
<category name="Category - level 3" />
</category>
<category name="Category - level 2">
<category name="Category - level 3" />
</category>
</category>
</catalog>
XML;
$xml = simplexml_load_string($string);
您可以像这样调用递归函数:
recurse_category($xml);
而这个功能可以这样写:
function recurse_category($categories, $depth = 0) {
foreach ($categories as $category) {
echo str_repeat(' ', 2*$depth);
echo (string)$category['name'];
echo '<br />';
if ($category->category) {
recurse_category($category->category, $depth + 1);
}
}
}
最后,运行此代码将提供此类输出:
Category - level 1
Category - level 2
Category - level 3
Category - level 2
Category - level 3
答案 3 :(得分:1)
使用simplexml和xpath作为精细
...但是作为旁注,如果您想要实现的只是获取文档DOMDocument::getElementsByTagName()中每个<category>
元素的name属性就足够了。
您可以通过dom_import_simplexml()和simplexml_import_dom()在DOM和simplexml之间切换。两者都使用相同的内部数据表示,因此不需要进行昂贵的转换。
$xml = '<?xml version="1.0" encoding="utf-8"?>
<catalog>
<category name="Category - level 1">
<category name="Category - level 2" />
<category name="Category - level 2">
<category name="Category - level 3" />
</category>
<category name="Category - level 2">
<category name="Category - level 3">
<category name="Category - level 4" />
</category>
</category>
</category>
</catalog>';
$doc = new DOMDocument;
$doc->loadxml($xml);
foreach( $doc->getElementsByTagName('category') as $c) {
echo $c->getAttribute('name'), "\n";
}
打印
Category - level 1
Category - level 2
Category - level 2
Category - level 3
Category - level 2
Category - level 3
Category - level 4