Как запросить 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 должен быть в скобках '['.