使用XPath从XML获取标记名称

时间:2011-06-28 03:24:24

标签: php xml xpath

我正在使用PHP 5.3+,特别是simplexml_load_string()。我已经尝试寻找一个没有运气的几个小时的解决方案,所以任何帮助将不胜感激。

我需要系统地识别某个级别的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函数的最佳配置是什么,所以寻找建议。

2 个答案:

答案 0 :(得分: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 :(得分: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
)