Получение имен тегов из XML с использованием XPath - PullRequest
2 голосов
/ 28 июня 2011

Я работаю с 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' не имеет 'гаража', поэтому все дочерние элементы в XML объединяются. Мне нужно иметь возможность идентифицировать все имена тегов, представленные ниже элемента 'property', в идеале исключая любые элементы, которые имеют дочерние элементы. Я мог бы работать с источниками, у которых есть дочерние элементы (в данном примере это «изображения»), но было бы неплохо, чтобы XPath также позаботился об этой части.

Причина этого в том, что мы агрегируем несколько XML-фидов данных свойств, которые имеют разные переменные тегов, и перед импортом нам необходимо иметь представление обо всех различных именах тегов, используемых в XML, прежде чем мы передадим эти данные через к остальной части программы.

Итак, есть ли запрос XPath, который можно построить? Производительность является фактором, и я не уверен, какова оптимальная конфигурация функции PHP, поэтому ищите предложения.

Ответы [ 2 ]

2 голосов
/ 28 июня 2011

Попробуйте что-то вроде этого

$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 голос
/ 28 июня 2011

Вы можете использовать функцию 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
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...