【问题标题】:Select some but not all child nodes选择一些但不是所有的子节点
【发布时间】:2010-10-20 10:30:00
【问题描述】:

我有以下 XML 结构:

<?xml version="1.0" encoding="ISO-8859-1"?>
<articles>
  <article id="1">
    <title>Article title 001</title>
    <short>Short text</short>
    <long>Long text</long>
  </article>
  <article id="2">
    <title>Article title 002</title>
    <short>Short text</short>
    <long>Long text</long>
  </article>
</articles>

我只想选择&lt;title&gt;&lt;short&gt;

目前使用它来显示所有内容:

 $queryResult = $xpathvar->query('//articles/article'); // works fine grabs all articles
 foreach($queryResult as $result){
   echo $result->textContent;
 }

预期的输出是:

文章标题 001

短文本

任何帮助将不胜感激。

有效的解决方案!

if ($artId == "") {
    $queryResult = $xpathvar->query('//articles/article/*'); // grab all children
    foreach($queryResult as $result){
      if($result->nodeName === 'title' || $result->nodeName === 'short') {
          echo $result->textContent;
      }
    }
}else{
    $queryResult = $xpathvar->query(sprintf('//articles/article[@id="%s"]/*', $artId)); // Show requested article
    foreach($queryResult as $result){
      if($result->nodeName === 'title' || $result->nodeName === 'long') {
          echo $result->textContent;
      }
    }
}

【问题讨论】:

  • 您真正希望看到什么输出?
  • 好问题,+1。请参阅我的答案以获得更有效的解决方案 - 也是一个更“XPath-y”的解决方案。 :)

标签: php xml xpath


【解决方案1】:

你可以使用

/articles/article/*[name()="title" or name()="short"]

它只会返回元素名称为“title”或“short”的任何“articles/article”的子级。


作为替代方案,将 XPath 更改为 /articles/article/* 以获取文章的所有子节点,并在迭代 $results 时检查 DOMNode::nodeName 是“标题”还是“短”,例如

$queryResult = $xpathvar->query('/articles/article/*'); // grab all children
foreach($queryResult as $result){
  if($result->nodeName === 'title' || $result->nodeName === 'short') {
      echo $result->textContent;
  }
}

如果你不想改变XPath,你必须迭代文章的childNodes,例如

$queryResult = $xpathvar->query('/articles/article');
foreach($queryResult as $result) {
  foreach($result->childNodes as $child) {       
  if($child->nodeName === 'title' || $child->nodeName === 'short') {
      echo $child->textContent;
  }
}

【讨论】:

  • 感谢 Gordon,您的第一个解决方案有效,但是...我还需要能够根据 ID 仅选择一篇文章并显示标题和长文本。
  • @StefWill XPath 将是 //articles/article[@id=1]/*[name()="title" or name()="long"]。看看这个Xpath Tutorial
  • +1 好答案。但是,当架构众所周知时,请不要以 // 运算符开头的表达式。
  • @Alejando 谢谢,也感谢编辑。实际上,我只是复制了 XPath,并没有理会它的初始部分。我知道你一直在告诉我 :) 但是当文档如上所示时,使用直接路径还是双斜杠会有所不同吗?或者换一种说法:它真正开始对什么文档大小或结构产生影响?
【解决方案2】:

使用

/*/*/*[self::title or self::short]

或者如果应该显示具有已知@id(比如“2”)的特定articletitleshort 子级:

/*/article[@id='2']/*[self::title or self::short]

尽可能避免使用// 缩写(当已知 XML 文档的结构时)。

使用// 经常会导致评估效率极低,因为// 会导致搜索以当前节点为根的整个(子)树。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-05
    • 2012-08-21
    相关资源
    最近更新 更多