php xpath xml解析for循环只显示第一个条目

时间:2013-07-19 19:38:29

标签: php xml xpath foreach simplexml

我有一个php simplexml xpath的愚蠢问题,我不明白。

xml结构:

<tv>
  <programme start="zeitbla" stop="zeitbla2" channel="19">
    <title>erstertitelbla</title>
    <desc>blablabeschreibung</desc>
    <category lang="ja_JP">情報</category>
    <category lang="en">information</category>
  </programme>
  <programme start="zeitbla" stop="zeitbla2" channel="19">
    <title>zweitertitelbla</title>
    <desc>blablabeschreibung</desc>
    <category lang="ja_JP">ニュース・報道</category>
    <category lang="en">news</category>
  </programme>
</tv>

php代码:

$domtemp = new domDocument;
$domtemp->load("file.xml");
$fullfile = simplexml_import_dom($domtemp);

foreach($fullfile->programme as $program){
    $category = $program->xpath('//category[@lang="en"]');
    echo $category[0]."\n";
}

我的问题是:

为什么我只得到每个循环传递中第一个条目的类别?

输出

information

information

修改

我解决了这个问题:

$domtemp = new domDocument;
$domtemp->load("file.xml");
$fullfile = simplexml_import_dom($domtemp);
foreach($sxe->programme as $program){
    $program  = simplexml_load_string($program->asXML());
    $category = $program->xpath('//category[@lang="en"]');
    echo "{$category[0]}\n";

但我仍然想知道为什么这不像我预期的那样有用。

问候

BluBb_mADe

2 个答案:

答案 0 :(得分:3)

基于@hakre's comment我对我的答案做了一些调整,所以你要做的只是对XPath查询进行一些小改动:

category[@lang="en"]

而不是

//category[@lang="en"]

因为这样您就可以将每个programme节点维护为查询上下文,而不是像以前一样维护整个XML文档。我创建了an example in codepad,您可以在其中看到它完全正常工作:

<?php
$xml = <<<XML
<tv>
  <programme start="zeitbla" stop="zeitbla2" channel="19">
    <title>erstertitelbla</title>
    <desc>blablabeschreibung</desc>
    <category lang="ja_JP">情報</category>
    <category lang="en">information</category>
  </programme>
  <programme start="zeitbla" stop="zeitbla2" channel="19">
    <title>zweitertitelbla</title>
    <desc>blablabeschreibung</desc>
    <category lang="ja_JP">ニュース・報道</category>
    <category lang="en">news</category>
  </programme>
</tv>
XML;

$sxe = new SimpleXMLElement($xml);

foreach($sxe->programme as $program){
    $category = $program->xpath('category[@lang="en"]');
    echo "{$category[0]}\n";
}

输出:

information
news

在旁注上,您可以使用simplexml_load_file function代替加载DOMDocument,然后将其导入SimpleXMLElement

答案 1 :(得分:0)

  

为什么我只得到每个循环传递中第一个条目的类别?

您只能获得第一个条目,因为您要求确切地说:

//category[@lang="en"]

此xpath显示:在文档中的任何位置提供任何 <category>元素。当xpath() 以文档顺序返回那些(因为底层的 libxml ,并与:XPath query result order进行比较)并获得第一个数组条目($category[0]0是第一个条目),你总是得到第一个条目。

正如您所看到的那样,您只是查询了这一点。这里重点是你理解//轴(双斜杠)。甚至认为// Descendant Axis (所以看着所有的孩子,孙子等等),单独使用它(在查询的开头)将首先去根-element(也称为文档元素)。

相反,您或者只是想寻找直接孩子(正如您的XML建议的那样):

category[@lang="en"]

- 或 - < - em>后代轴相对到上下文节点:

.//category[@lang="en"]
^
`----  this dot prevents to go up to the root element

- 或 - 以下,更具表现力(和更长时间写入)(检查可用的不同轴):

descendant::category[@lang="en"]
child::category[@lang="en"]

正如您所看到的,如果您了解查询,则很容易修复。

希望这能为您提供期待已久的解释。 BTW这种错误有点普遍,你不是第一个要求这个的人。只需稍微查看xpath查询,并尝试用自己的语言表达它的作用并与规范进行比较。使用Xpath越流畅,就越容易。

参见: