0

我正在使用 SimpleXML 循环遍历 XML 文件,并尝试每次从 Previous 和 Next 节点中提取特定的数据(特别是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”变量不起作用。他们返回一个空白结果。我究竟做错了什么?

非常感谢任何指导。

4

3 回答 3

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][position()=1]在位置路径中,comic将返回所有前面或后面的节点。

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

所以使用这个位置路径

$prevIssue_arr = $comic->xpath('preceding-sibling::comic[1]/mainsection/series');
$prevIssue = (isset($prevIssue_arr[0])) ? $prevIssue_arr[0]->displayname : '';
$nextIssue_arr = $comic->xpath('following-sibling::comic[1]/mainsection/series');
$nextIssue = (isset($nextIssue_arr[0])) ? $nextIssue_arr[0]->displayname : '';
于 2012-09-30T09:17:28.077 回答
2

问题在这里:

preceding-sibling::*

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

following-sibling::*

选择所有以下同级元素。

您只需要一个 - 直接在前的兄弟姐妹或直接跟随的兄弟姐妹 - 分别

preceding-sibling::*[1]

following-sibling::*[1]
于 2012-09-30T14:11:12.343 回答
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
);
于 2012-09-30T14:22:53.830 回答