2010-04-05 17 views
4

介紹文件:提取數據形式的XML使用SimpleXML PHP中

我想通過與靈活類結構的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> 

我現在擁有的一切:

我沒有問題,通過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']; 
     } 
    } 
} 

回答

6

獲取的名字從你的類別屬性,很可能是最快的,當通過XPath的,例如做

$categoryNames = $doc->xpath('//category/@name'); 

但是,如果你想在任意嵌套的XML結構遞歸迭代,你也可以使用SimpleXMLIterator,例如與$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 

就像開頭說的,當時只是想獲取所有name屬性,使用XPath,因爲遍歷每個節點慢。只有當你想用節點做更復雜的事情時才使用這種方法,例如向它們添加一些東西。

2
<?php 
$xml= new SimpleXMLElement('.....'); 
foreach ($xml->xpath('//category') as $cat) 
{ 
    echo $cat['name']; 
} 
+1

由於OP是name屬性之後,你可以簡單地使用'//類別/ @ name'您的XPath。這將返回名稱屬性節點而不是類別元素。 – Gordon 2010-04-05 14:06:02

1

一個可能的解決辦法是寫一個recursive function,這將:

    當前深度
    • 寫入當前類別
    • 的名字
    • 的foreach類別如果它有兒童分類,自稱這些。

這種解決方案的優點是你可以跟蹤當前深度你,你的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('&nbsp; ', 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 
1

使用SimpleXML和XPath細
......但只是作爲一個旁註,如果你想要實現的是讓每個name屬性,每<category>元素的文檔中DOMDocument::getElementsByTagName()就足夠了。
您可以通過dom_import_simplexml()和在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