php xpath查询根据重复子节点中的值获取父节点

时间:2015-03-06 14:07:11

标签: php xml xpath

我的XML文件结构如下:

<pictures>
    <picture>
        <title></title>
        <description></description>
        <facts>
            <date></date>
            <place>Unites States</place>
        </facts>
        <people>
            <person>John</person>
            <person>Sue</person>
        </people>
    </picture>
    <picture>
        <title></title>
        <description></description>
        <facts>
            <date></date>
            <place>Canada</place>
        </facts>
        <people>
            <person>Sue</person>
            <person>Jane</person>
        </people>
    </picture>
    <picture>
        <title></title>
        <description></description>
        <facts>
            <date></date>
            <place>Canada</place>
        </facts>
        <people>
            <person>John</person>
            <person>Joe</person>
            <person>Harry</person>
        </people>
    </picture>
<pictures>

在一个案例中,我需要搜索where =“Canada”的图片。我有一个XPath可以做到这一点,因此:

$place = "Canada";
$pics = ($pictures->xpath("//*[place='$place']"));

这会拉动整个“图片”节点,因此我可以显示标题,说明等。 我有另一个需要找到所有人= $ person的图片。我使用与上面相同类型的查询:

$person = "John";
$pics = ($pictures->xpath("//*[person='$person']"));

在这种情况下,查询显然知道John有2张图片,但我没有获得其他节点的任何值。我猜它与重复的子节点有关,但无法弄清楚如何重构XPath以拉出我在人物上匹配的每个图片节点。我尝试使用属性而不是值(并相应地修改了查询),但得到了相同的结果。 谁能告诉我在这里缺少什么?

1 个答案:

答案 0 :(得分:3)

让我们先替换变量。这使PHP脱离了图片。问题只是正确的XPath表达式。

//*[place='Canada']

匹配具有子元素节点place且文本内容为Canada的任何元素节点。

这是facts元素节点 - 而不是picture

获取图片节点略有不同:

//picture[facts/place='Canada']

这将选择与条件匹配的任何深度的任何图像节点。

picture[facts/place='Canada']

将使用提供的XML返回相同的结果,但更具体,仅匹配作为文档元素的子元素的picture个元素节点。

现在验证people节点大致相同:

picture[people/person="John"]

您甚至可以将这两个条件结合起来:

picture[facts/place="Canada" and people/person="John"]

这是一个小型演示:

$element = new SimpleXMLElement($xml);

$expressions = [
  '//*[place="Canada"]',
  '//picture[facts/place="Canada"]',
  'picture[facts/place="Canada"]',
  'picture[people/person="John"]',
  'picture[facts/place="Canada" and people/person="John"]',
];

foreach ($expressions as $expression) {
  echo $expression, "\n", str_repeat('-', 60), "\n";
  foreach ($element->xpath($expression) as $index => $found) {
     echo '#', $index, "\n", $found->asXml(), "\n";
  }
  echo "\n";
}

提示:您在XPath表达式中使用dyamic值。 XPath 1.0中的字符串文字不支持任何类型的转义。变量中的引号可以打破你的表达。请参阅this answer