Мне нужно прочитать атрибуты «id», но я получаю либо пустые строки, либо строку, содержащую «один», в зависимости от используемого выражения XPath.
Я намеренно использую метод «запроса», чтобы получить DOMNodeList с узлами, тогда я хочу работать с ними. Пожалуйста, проверьте следующий код:
<?php
$xml = '
<ROOT>
<MEMBER id = "one" />
<MEMBER id = "two" />
</ROOT>
';
$dom = new \DOMDocument('1.0', 'utf-8');
$dom->loadXML($xml);
$xpath = new DOMXpath($dom);
$members = $xpath->query('/ROOT/MEMBER'); // object of class DOMNodeList
foreach ($members as $member) {
echo($dom->saveXML($member)); // displays <MEMBER id = "one"/> and <MEMBER id = "two"/> as expected
$id = $xpath->evaluate('string(/MEMBER/@id)', $member); // let's read the id attribute
var_dump($id); // returns string(0) "" in both cases - how come?
$id = $xpath->evaluate('string(//MEMBER/@id)', $member); // should make no difference
var_dump($id); // string(3) "one" in both cases
}
Ага, это работает. Но MEMBER
является корневым узлом, поэтому /MEMBER/@id
тоже должен работать. Я все еще в замешательстве ...
В вашем входном корневом XML-узле - ROOT
В $ dom это ROOT
, в $ member корневой узел - MEMBER
.
если вы используете /MEMBER/@id
, это означает, что ваш текущий контекст должен быть похож на <MEMBER><MEMBER id = "one" /><MEMBER id = "two" /></MEMBER>
??? Я не понимаю. Я не уверен, что вы имеете в виду под текущим контекстом. Вернемся к DOMNodeList. Каждый запуск foreach
создает экземпляр DOMElement ($ member). Метод saveXML () выводит <MEMBER id = "one"/>
для первого $ member. Итак, <MEMBER> - корневой узел $ member, верно? И согласно w3schools.com/xml/xpath_syntax.asp я должен иметь возможность использовать выражение /MEMBER/@id
для получения атрибута корневого узла.
в foreach вы уже находитесь в контексте MEMBER
, поэтому вместо /MEMBER/@id
используйте только @id
, надеюсь, вы получите желаемый результат.
На самом деле в foreach ($members as $member)
есть два <MEMBER id = "one" />
, и <MEMBER id = "two" />
будут контекстом, поэтому вы уже находитесь в элементе MEMBER
, вам просто нужно выбрать @id
из текущего контекста.
Если вы напечатаете $member
, тогда вы будете знать, что хранится в этом контексте, тогда картина будет ясной.
Примите ответ, если он вам подходит.
в foreach вы уже находитесь в контексте
MEMBER
, поэтому вместо/MEMBER/@id
используйте только@id
, надеюсь, вы получите желаемый результат.