抓取上一个/下一个节点的特定部分

时间:2012-09-30 05:50:48

标签: php xpath simplexml

我正在使用SimpleXML循环遍历XML文件,并试图从Previous中提取特定的数据(具体来说, series-> displayname 属性)每次都有下一个节点。

以下是XML结构的示例:

<comic>
      <id>117</id>
      <index>1</index>
      <mainsection>
        <pagecount>33</pagecount>
        <series>
          <displayname>Amazing Story</displayname>
          <sortname>Amazing Story</sortname>
        </series>
      </mainsection>
</comic>
<comic>
      <id>102</id>
      <index>1</index>
      <mainsection>
        <pagecount>33</pagecount>
        <series>
          <displayname>Fantastic Tale</displayname>
          <sortname>Fantastic Tale</sortname>
        </series>
      </mainsection>
</comic>
<comic>
      <id>85</id>
      <index>1</index>
      <mainsection>
        <pagecount>33</pagecount>
        <series>
          <displayname>The Great Tale</displayname>
          <sortname>The Great Tale</sortname>
        </series>
      </mainsection>
</comic>

以下是我在循环中使用的结构示例:

$prevIssue = $comic->xpath('preceding-sibling::*')->mainsection->series->displayname;
$nextIssue = $comic->xpath('following-sibling::*')->mainsection->series->displayname;

echo '
<li class="issue" id="' . $seriesCat . '">
<h3>' . $comicSeriresName . '</h3>
   <div id="details">
   <span id="publisher">' . $comicPublisher . '</span><br>
    The last series was called "' . $prevIssue . '<br>
    The next series is called "' . $nextIssue . '<br>
   </div>
</li>'; 

然而,'nextIssue'和'prevIssue'变量不起作用。他们返回一个空白的结果。我做错了什么?

非常感谢任何指导。

3 个答案:

答案 0 :(得分:2)

尝试以下代码

$prevIssue_arr = $comic->xpath('preceding-sibling::*[1]');
$prevIssue = (isset($prevIssue_arr[0])) ? $prevIssue_arr[0]->mainsection->series->displayname : '';
$nextIssue_arr = $comic->xpath('following-sibling::*[1]');
$nextIssue = (isset($nextIssue_arr[0])) ? $nextIssue_arr[0]->mainsection->series->displayname : '';

echo ...

[已编辑]

其他人已经解释了代码无效的原因

一个是xpath()方法返回一个SimpleXMLElement对象数组。如果未找到匹配的节点,则返回空数组。

另一个是在位置路径中没有谓词{{​​1}}或[1]的情况下,将返回所有前面或后面的[position()=1]节点。

或者,您可以使用位置路径comic从刚出现的兄弟中获取所需的'following-sibling::comic[1]/mainsection/series'节点。如果有多个series个节点,则必须给出位置,否则将返回所有节点。

所以使用这个位置路径

series

答案 1 :(得分:2)

问题在于:

preceding-sibling::*

选择所有之前的兄弟元素。

following-sibling::*

选择 all 以下兄弟元素。

你只需要一个 - 直接在先兄弟姐妹或直接跟随兄弟姐妹 - 分别

preceding-sibling::*[1]

following-sibling::*[1]

答案 2 :(得分:1)

正如其他答案所触及但未明确解释的部分问题在于,与SimpleXML对象上的大多数操作不同,->xpath()返回数组,而不是另一个SimpleXML对象。 (这可能是为了避免让SimpleXML对象包含整个文档中完全不相关的节点。)

因此,此行将失败,因为您将数组视为对象:

$prevIssue = $comic->xpath('preceding-sibling::*')->mainsection->series->displayname;

在PHP 5.4中,以下是有效的语法(在返回后立即索引到数组中):

$prevIssue = $comic->xpath('preceding-sibling::*')[0]->mainsection->series->displayname; 

但是对于早期版本的PHP,或者如果XPath有时可能返回0结果,则需要一个中间变量:

$prevSiblings = $comic->xpath('preceding-sibling::*');
$prevIssue = (
    ( count($prevSiblings) > 0 )
    ? $prevSiblings[0]->mainsection->series->displayname
    : NULL
);