2011-06-28 98 views
2

我正在使用PHP 5.3+,特別是simplexml_load_string()。我試過尋找解決方案几個小時不運氣,所以任何幫助將不勝感激。使用XPath從XML獲取標籤名稱

我需要一個系統的方法來識別某個級別上的XML文件中存在的所有標籤名稱。

例XML:

<?xml version="1.0"?> 
<properties> 
    <property> 
    <ID>243</ID> 
    <area>5,000</area> 
    <bathrooms>5</bathrooms> 
    <bedrooms>4</bedrooms> 
    <images> 
     <image>http://urltoimage.com/image1.jpg</image> 
     <image>http://urltoimage.com/image2.jpg</image> 
    </image> 
    </property> 
    <property> 
    <ID>332</ID> 
    <garage>2</garage> 
    <bathrooms>2</bathrooms>  
    <images> 
     <image>http://urltoimage.com/image5.jpg</image> 
     <image>http://urltoimage.com/image1.jpg</image> 
    </image>  
    </property> 
<properties> 

我需要能夠檢索的數組:

  • ID
  • 區域
  • 浴室
  • 臥室
  • 車庫

正如您所看到的,第一個'property'元素沒有'garage',所以XML中的所有子元素都被聚合。我需要能夠識別'property'元素下面的所有標籤名稱,理想情況下排除任何有子元素的元素。我可以解決有孩子的滲出元素(本例中爲'圖像') - 但是XPath也會很好地處理該部分。

背後的原因 - 我們正在彙總具有不同標記變量的屬性數據的多個XML源,並且在導入之前,我們需要先了解XML中使用的所有不同標記名稱,然後再傳遞該數據轉移到程序的其餘部分。

那麼,是否有可以構建的XPath查詢?性能是一個因素,我不確定PHP函數的最佳配置是什麼,所以尋找建議。

+0

這兩種解決方案的工作 - 謝謝你們。我做了一些基準測試,看哪一個更快,而且他們非常接近。對於一個小的XML文件,Phil的方法更快(0.008 vs 0.010秒)。對於較大的XML文件,它們幾乎完全相同。 – Andy

回答

2

嘗試這樣的事情

$doc = simplexml_load_string($xml); 
$nodes = $doc->xpath('//property/*[not(*)]'); 
$properties = array(); 
foreach ($nodes as $node) { 
    $properties[$node->getName()] = true; 
} 
$properties = array_keys($properties); 

foreach循環,你可以檢查,看看是否已經輸入的值,但我想上面會更快。

1

您需要使用SimpleXMLElement::children()函數來查找屬性的子項。

例子:

<?php 

$string = <<<END 
<?xml version="1.0"?> 
<properties> 
    <property> 
    <ID>243</ID> 
    <area>5,000</area> 
    <bathrooms>5</bathrooms> 
    <bedrooms>4</bedrooms> 
    <images> 
     <image>http://urltoimage.com/image1.jpg</image> 
     <image>http://urltoimage.com/image2.jpg</image> 
    </images> 
    </property> 
    <property> 
    <ID>332</ID> 
    <garage>2</garage> 
    <bathrooms>2</bathrooms>  
    <images> 
     <image>http://urltoimage.com/image5.jpg</image> 
     <image>http://urltoimage.com/image1.jpg</image> 
    </images>  
    </property> 
</properties> 
END; 

// Load the XML using the SimpleXML class. 
$xml = simplexml_load_string($string); 

// Loop through all of the properties. 
foreach ($xml->property as $property) 
{ 
    // Reset the property tags array for this property. 
    $property_tags = array(); 

    foreach ($property->children() as $children) 
    { 
    // If a tag was found, add it to the array. 
    if (! empty($children[0])) 
     $property_tags[] = $children[0]->getName(); 
    } 

    // Output the list to the screen (this could be removed). 
    print_r($property_tags); 
} 

輸出:

Array 
(
    [0] => ID 
    [1] => area 
    [2] => bathrooms 
    [3] => bedrooms 
    [4] => images 
) 
Array 
(
    [0] => ID 
    [1] => garage 
    [2] => bathrooms 
    [3] => images 
) 

如果您想獲得所有可用標籤的列表(包含在XML文檔中的所有屬性),簡單地這樣做:

// Loop through all of the properties. 
foreach ($xml->property as $property) 
{ 
    foreach ($property->children() as $children) 
    { 
    // If a tag was found, add it to the array if it's not already in it. 
    if (! empty($children[0]) && ! in_array($children[0]->getName(), $property_tags)) 
     $property_tags[] = $children[0]->getName(); 
    } 
} 

// Output the list to the screen (this could be removed). 
print_r($property_tags); 

輸出:

Array 
(
    [0] => ID 
    [1] => area 
    [2] => bathrooms 
    [3] => bedrooms 
    [4] => images 
    [5] => garage 
) 
+0

你的回答非常好,但是它比其他方法慢。儘管如此,謝謝你的偉大答案。 – Andy