【问题标题】:xpath with simplexml not able to access nested element带有simplexml的xpath无法访问嵌套元素
【发布时间】:2021-06-06 16:42:33
【问题描述】:

我有一个这样的 xml:

  <?xml version="1.0" encoding="UTF-8"?>
  <foo SeqNum="1">
    <bar>1234</bar>
  </foo>
  <foo SeqNum="20">
    <bar>6789</bar>
  </foo>

我正在尝试使用此查询获取值 6789

$xml = "<?xml version="1.0" encoding="UTF-8"?>
  <foo SeqNum="1">
    <bar>1234</bar>
  </foo>
  <foo SeqNum="20">
    <bar>6789</bar>
  </foo>";
$simple = new SimpleXMLElement($xml);
$result = $simple->xpath('//*[@SeqNum="20"]/bar/'); // result gives me nothing

所以我试着让父母像这样

$result = $simple->xpath('//*[@SeqNum="20"]')[0]->asXML();

这给了我:

  <foo SeqNum="20">
    <bar>6789</bar>
  </foo>

所以我快到了,但我真的被我不理解的东西困住了。谢谢!

【问题讨论】:

  • 尝试不带尾随 /。请注意,有效的 XML 需要一个文档元素。
  • @ThW 谢谢。我刚试了没用。
  • 演示,固定3v4l.org/UrSV0
  • 谢谢!我刚刚意识到我的示例并不完整,并且没有包含定义的命名空间。看起来我需要注册命名空间才能对 xml 执行任何查询。当我有时间时,我会修复这个例子。非常感谢您,请随时将解决方案作为解决方案发布,我会这样标记。
  • 是的,您必须在调用 xpath() 方法的任何 SimpleXMLElement 实例上注册命名空间。实际上,DOMXpath::evaluate() 的代码更少。

标签: php xml simplexml


【解决方案1】:

这里有几个问题中的错误。 XML 需要一个根元素,而结尾的 / 会破坏表达式。字面引号需要改为单引号(或者所有内部双引号需要转义。)

固定示例:

$xml = '<?xml version="1.0" encoding="UTF-8"?>
<foo>
  <foo SeqNum="1">
    <bar>1234</bar>
  </foo>
  <foo SeqNum="20">
    <bar>6789</bar>
  </foo>
</foo>';

$simple = new SimpleXMLElement($xml);
$result = $simple->xpath('//*[@SeqNum="20"]/bar');
var_dump((string)$result[0]);

输出:

string(4) "6789"

使用命名空间

如果您的 XML 使用命名空间,则必须为此命名空间 URI 定义别名/前缀,并在 Xpath 表达式中使用它。

$xml = <<<'XML'
<?xml version="1.0" encoding="UTF-8" ?> 
<p:foo xmlns:p="http://www.example.com">   
   <p:foo SeqNum="1">     
     <p:bar>1234</p:bar>   
   </p:foo>   
   <p:foo SeqNum="20">     
     <p:bar>6789</p:bar>   
   </p:foo> 
</p:foo> 
XML;
 
$simple = new SimpleXMLElement($xml);
$simple->registerXpathNamespace('e', 'http://www.example.com');
$result = $simple->xpath('//*[@SeqNum="20"]/e:bar');
var_dump((string)$result[0]);

该示例为表达式使用不同的别名以表明文档和表达式是分开的 - 只有命名空间 URI 必须匹配。

命名空间必须是唯一的,因此它们是使用 URI(URL 的超集)定义的。因为这会在节点名称中使用混乱的别名。以下3个元素都可以读作{http://www.example.com}bar

  • &lt;p:bar xmlns:p="http://www.example.com"/&gt;
  • &lt;e:bar xmlns:e="http://www.example.com"/&gt;
  • &lt;bar xmlns="http://www.example.com"/&gt;

【讨论】:

  • 我有一个问题,关于如何在 xml 更改为 $xml = &lt;&lt;&lt;'XML' &lt;?xml version="1.0" encoding="UTF-8" xmlns:p="www.example.com"?&gt; &lt;p:foo&gt; &lt;p:foo SeqNum="1"&gt; &lt;p:bar&gt;1234&lt;/p:bar&gt; &lt;/p:foo&gt; &lt;p:foo SeqNum="20"&gt; &lt;p:bar&gt;6789&lt;/p:bar&gt; &lt;/p:foo&gt; &lt;/p:foo&gt; XML; 的情况下更新它,再次感谢!
  • 我添加了一个带有命名空间的示例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-16
  • 1970-01-01
  • 1970-01-01
  • 2021-07-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多