Как запросить XML-файл с помощью xpath (php)?

Я пытаюсь запросить XML-файл, используя XPath. Но по возвращении я ничего не получаю. Я думаю, что я отформатировал запрос false.

XML

<subject id="Tom">
   <relation unit="ITSupport" role="ITSupporter" />
  </subject>

PHP

$xpath = new DOMXpath($doc);
            $role = 'ITSupporter';
           $elements = $xpath-> query("//subject/@id[../relation/@role='".$role."']");              
           foreach ($elements as $element) {    
              $name = $element -> nodeValue;
              $arr[$i] = $name;
              $i = $i + 1;
           }    

Как я могу получить идентификатор TOM? Я хочу сохранить его, например, в $var

3 ответа

Решение

Создание выражения Xpath:

  • Получить любой subject элемент
    //subject
  • ... с дочерним элементом relation
    //subject[relation]
  • ... это имеет role атрибут с заданным текстом
    //subject[relation/@role="ITSupporter"]
  • ... и получить @id атрибут subject
    //subject[relation/@role="ITSupporter"]/@id

Кроме того, источник может быть очищен. PHP массивы могут использовать $array[] синтаксис, чтобы вставить новые элементы в них.

Собрать вместе:

$xml = <<<'XML'
<subject id="Tom">
  <relation unit="ITSupport" role="ITSupporter" />
</subject>
XML;

$role = 'ITSupporter';

$document = new DOMDocument();
$document->loadXML($xml);
$xpath = new DOMXpath($document);

$ids = [];
foreach ($xpath->evaluate("//subject[relation/@role='".$role."']/@id") as $idAttribute) {
  $ids[] = $idAttribute->value;
}
var_dump($ids);

Выход:

array(1) { 
  [0]=> 
  string(3) "Tom" 
}

Если вы ожидаете только один результат, вы можете разыграть его в Xpath:

$id = $xpath->evaluate(
  "string(//subject[relation/@role='".$role."']/@id)"
);
var_dump($id);

Выход:

string(3) "Tom"

Пространства имен XML

Глядя на пример, размещенный в комментарии, ваш XML использует пространство имен http://cpee.org/ns/organisation/1.0 без префикса. Синтаксический анализатор XML разрешит его, чтобы вы могли читать узлы как {http://cpee.org/ns/organisation/1.0}subject, Вот 3 примера, которые все решают к этому:

  • <subject xmlns="http://cpee.org/ns/organisation/1.0"/>
  • <cpee:subject xmlns:cpee="http://cpee.org/ns/organisation/1.0"/>
  • <c:subject xmlns:c="http://cpee.org/ns/organisation/1.0"/>

То же самое должно случиться с выражением Xpath. Однако Xpath не имеет пространства имен по умолчанию. Вам необходимо зарегистрировать префикс по вашему выбору. Это позволяет движку Xpath разрешать что-то вроде //org:subject в //{http://cpee.org/ns/organisation/1.0}subject,

PHP не нужно сильно менять:

$xml = <<<'XML'
<subject id="Tom" xmlns="http://cpee.org/ns/organisation/1.0">
  <relation unit="ITSupport" role="ITSupporter" />
</subject>
XML;

$role = 'ITSupporter';

$document = new DOMDocument();
$document->loadXML($xml);
$xpath = new DOMXpath($document);
// register a prefix for the namespace
$xpath->registerNamespace('org', 'http://cpee.org/ns/organisation/1.0');

$ids = [];
// address the elements using the registered prefix
$idAttributes = $xpath->evaluate("//org:subject[org:relation/@role='".$role."']/@id");
foreach ($idAttributes as $idAttribute) {
  $ids[] = $idAttribute->value;
}
var_dump($ids);

Попробуйте этот XPath

//subject[relation/@role='".$role."']/@id

Вы применяли предикат на id атрибут, а не на subject элемент.

Получение элемента по id аналогично получению содержимого $role. Итак, как и следующие;$xpath->query("//*[@id='$id']")->item(0);Другими словами, @id должен быть в скобках '['.

Другие вопросы по тегам