php xpath 查询以根据重复 child 节点中的值获取 parent 节点
php xpath query to get parent node based on value in repeating child nodes
我有一个 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>
在一种情况下,我需要搜索 place="Canada" 的图片。我有一个 XPath 可以很好地做到这一点,因此:
$place = "Canada";
$pics = ($pictures->xpath("//*[place='$place']"));
这会拉取整个 "picture" 节点,因此我能够显示标题、描述等。
我还需要找到 person = $person 的所有图片。我使用与上面相同类型的查询:
$person = "John";
$pics = ($pictures->xpath("//*[person='$person']"));
在这种情况下,查询显然知道有 2 张 John 的照片,但我没有得到其他节点的任何值。我猜它与重复的 child 节点有关,但无法弄清楚如何重构 XPath 以在我与人匹配的每个位置拉出所有图片节点。我尝试使用属性而不是值(并相应地修改了查询),但得到了相同的结果。
谁能告诉我这里缺少什么?
我们先替换变量。这将 PHP 排除在外。问题只是正确的 XPath 表达式。
//*[place='Canada']
匹配具有子元素节点 place
和文本内容 Canada
的任何元素节点。
这是 facts
元素节点 - 不是 picture
。
获取图片节点略有不同:
//picture[facts/place='Canada']
这将 select 任何深度处符合条件的任何图片节点。
picture[facts/place='Canada']
return 与所提供的 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 表达式中使用了动态值。 XPath 1.0 中的字符串文字不支持任何类型的转义。变量中的引号可能会打断您的表达。参见 this answer。
我有一个 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>
在一种情况下,我需要搜索 place="Canada" 的图片。我有一个 XPath 可以很好地做到这一点,因此:
$place = "Canada";
$pics = ($pictures->xpath("//*[place='$place']"));
这会拉取整个 "picture" 节点,因此我能够显示标题、描述等。 我还需要找到 person = $person 的所有图片。我使用与上面相同类型的查询:
$person = "John";
$pics = ($pictures->xpath("//*[person='$person']"));
在这种情况下,查询显然知道有 2 张 John 的照片,但我没有得到其他节点的任何值。我猜它与重复的 child 节点有关,但无法弄清楚如何重构 XPath 以在我与人匹配的每个位置拉出所有图片节点。我尝试使用属性而不是值(并相应地修改了查询),但得到了相同的结果。 谁能告诉我这里缺少什么?
我们先替换变量。这将 PHP 排除在外。问题只是正确的 XPath 表达式。
//*[place='Canada']
匹配具有子元素节点 place
和文本内容 Canada
的任何元素节点。
这是 facts
元素节点 - 不是 picture
。
获取图片节点略有不同:
//picture[facts/place='Canada']
这将 select 任何深度处符合条件的任何图片节点。
picture[facts/place='Canada']
return 与所提供的 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 表达式中使用了动态值。 XPath 1.0 中的字符串文字不支持任何类型的转义。变量中的引号可能会打断您的表达。参见 this answer。