xpath 让我失望
xpath is failing me
我有一个 xml 结构:
<Articles>
<Article ID="111">
<author>Peter Paul</author>
<pubDate>01/01/2015</pubDate>
<Translations>
<lang1>English</lang1>
<lang2>French</lang2>
<lang3>Arab</lang3>
<lang3>Chinese</lang3>
</Translations>
</Article>
<Article ID="222">
<author>Monkey Rice</author>
<pubDate>01/01/2016</pubDate>
<Translations>
<lang1>English</lang1>
</Translations>
</Article>
<Article ID="333">
<author>John Silas</author>
<pubDate>01/01/2017</pubDate>
<Translations>
<lang1>English</lang1>
<lang2>French</lang2>
<lang3>Arab</lang3>
<lang3>Chinese</lang3>
</Translations>
</Article>
</Articles>
我创建了一个方法 AddRecordByInfoMatch() 试图
将新节点添加到任何给定 ID 的任意位置只要
因为存在匹配项:
function AddRecordByInfoMatch($ParentID, $Info_1, $Info_2, $Info_3, array $Record){
$xml = new SimpleXMLElement(blabla.xml);
$result = $xml->xpath("//*[@ID='$ParentID']"); //get the article ID
if(!empty($result)){
foreach($result[0] as $key => $value){
$noofChild = count($value);
//three info match may lakely be within 3 sub-nodes
if($noofChild >= 3){
$query = "//*[node()[contains(text(), \"$Info_1\")] and node()[contains(text(), \"$Info_2\")] and node()[contains(text(), \"$Info_3\")]]";
$data = $xml->xpath($query);
if(!empty($data[0]){
foreach ($Record as $nodname => $val){
$data[0]->addChild($nodname, $val);
}
}
}
}
}
}
考虑到 ID = 333,我像这样测试它:
XMLAddRecordByInfoMatch(333, "English", "French", "Chinese", array(
"syntax" => irrelevant,
"adjectives" => None,
"verbs" => 2,
"prepositions" => 5
));
不幸的是,输出;显示后,将新记录添加到 Article
ID 111 给出 :
...
<Article ID="111">
<author>Peter Paul</author>
<pubDate>01/01/2015</pubDate>
<Translations>
<lang1>English</lang1>
<lang2>French</lang2>
<lang3>Arab</lang3>
<lang3>Chinese</lang3>
<syntax>irrelevant</syntax>
<adjectives>None</adjectives>
<verbs>2</verbs>
<prepositions>5</prepositions>
</Translations>
</Article>
...
我希望它在 ID 333 的文章节点中,它
我在函数调用中指定。我在我的 xpath xpression 中做错了什么?或者如何
我能做到吗?任何帮助都将受到高度重视。大家新年快乐
what am I doing wrong in my xpath xpression ?
我能发现的一个错误是(当用户在 Whosebug 上的 PHP 标签下询问 xpath 时很常见)您没有意识到脚本中可能存在的 xpath 注入。
因此,对于 PHP 示例,我会确保它是安全的,所使用的函数取自 Mitigating XPath Injection Attacks in PHP,其中还包含有关该主题的更多信息。
除了那个(常见的)错误之外,直接进入视野的是您可以在这里做很多事情,而您可以只用一个 XPath 表达式来表达它。
您希望第一个元素具有特定值的 ID 属性,然后包含一个子元素,该子元素包含至少三个子元素,其中三个必须包含三个文本中的一个。
对于 333 的示例 ID 和三个示例文本 "English"、"French" 和 "Chinese",XPath 查询如下所示:
(
//*[@ID=333]
/*[ count(*) > 2
and (
*[contains(., 'English')]
and *[contains(., 'French')]
and *[contains(., 'Chinese')]
)
]
/..
)[1]
如您所见,在其周围包裹更多 PHP 代码意义不大。
在这些最明显的点旁边,应该注意的是,信息作为具有三个值的数组比三个编号变量 ($infos = ["English", "French", "Chinese"];
) 更好。
示例:
$expr = sprintf("
(
//*[@ID=%d]
/*[ count(*) > 2
and (
*[contains(., %s)]
and *[contains(., %s)]
and *[contains(., %s)]
)
]
/..
)[1]",
$parentId, xpath_string($infos[0]), xpath_string($infos[1]), xpath_string($infos[2])
);
list($element) = $xml->xpath($expr) + [NULL];
if (empty($element)) {
// element not found
return;
}
// extend element
foreach ($record as $nodname => $val) {
$element->addChild($nodname, $val);
}
这给出了预期的结果:
<Article ID="333">
<author>John Silas</author>
<pubDate>01/01/2017</pubDate>
<Translations>
<lang1>English</lang1>
<lang2>French</lang2>
<lang3>Arab</lang3>
<lang3>Chinese</lang3>
</Translations>
<syntax>irrelevant</syntax><adjectives>None</adjectives><verbs>2</verbs><prepositions>5</prepositions></Article>
我有一个 xml 结构:
<Articles>
<Article ID="111">
<author>Peter Paul</author>
<pubDate>01/01/2015</pubDate>
<Translations>
<lang1>English</lang1>
<lang2>French</lang2>
<lang3>Arab</lang3>
<lang3>Chinese</lang3>
</Translations>
</Article>
<Article ID="222">
<author>Monkey Rice</author>
<pubDate>01/01/2016</pubDate>
<Translations>
<lang1>English</lang1>
</Translations>
</Article>
<Article ID="333">
<author>John Silas</author>
<pubDate>01/01/2017</pubDate>
<Translations>
<lang1>English</lang1>
<lang2>French</lang2>
<lang3>Arab</lang3>
<lang3>Chinese</lang3>
</Translations>
</Article>
</Articles>
我创建了一个方法 AddRecordByInfoMatch() 试图 将新节点添加到任何给定 ID 的任意位置只要 因为存在匹配项:
function AddRecordByInfoMatch($ParentID, $Info_1, $Info_2, $Info_3, array $Record){
$xml = new SimpleXMLElement(blabla.xml);
$result = $xml->xpath("//*[@ID='$ParentID']"); //get the article ID
if(!empty($result)){
foreach($result[0] as $key => $value){
$noofChild = count($value);
//three info match may lakely be within 3 sub-nodes
if($noofChild >= 3){
$query = "//*[node()[contains(text(), \"$Info_1\")] and node()[contains(text(), \"$Info_2\")] and node()[contains(text(), \"$Info_3\")]]";
$data = $xml->xpath($query);
if(!empty($data[0]){
foreach ($Record as $nodname => $val){
$data[0]->addChild($nodname, $val);
}
}
}
}
}
}
考虑到 ID = 333,我像这样测试它:
XMLAddRecordByInfoMatch(333, "English", "French", "Chinese", array(
"syntax" => irrelevant,
"adjectives" => None,
"verbs" => 2,
"prepositions" => 5
));
不幸的是,输出;显示后,将新记录添加到 Article ID 111 给出 :
...
<Article ID="111">
<author>Peter Paul</author>
<pubDate>01/01/2015</pubDate>
<Translations>
<lang1>English</lang1>
<lang2>French</lang2>
<lang3>Arab</lang3>
<lang3>Chinese</lang3>
<syntax>irrelevant</syntax>
<adjectives>None</adjectives>
<verbs>2</verbs>
<prepositions>5</prepositions>
</Translations>
</Article>
...
我希望它在 ID 333 的文章节点中,它 我在函数调用中指定。我在我的 xpath xpression 中做错了什么?或者如何 我能做到吗?任何帮助都将受到高度重视。大家新年快乐
what am I doing wrong in my xpath xpression ?
我能发现的一个错误是(当用户在 Whosebug 上的 PHP 标签下询问 xpath 时很常见)您没有意识到脚本中可能存在的 xpath 注入。
因此,对于 PHP 示例,我会确保它是安全的,所使用的函数取自 Mitigating XPath Injection Attacks in PHP,其中还包含有关该主题的更多信息。
除了那个(常见的)错误之外,直接进入视野的是您可以在这里做很多事情,而您可以只用一个 XPath 表达式来表达它。
您希望第一个元素具有特定值的 ID 属性,然后包含一个子元素,该子元素包含至少三个子元素,其中三个必须包含三个文本中的一个。
对于 333 的示例 ID 和三个示例文本 "English"、"French" 和 "Chinese",XPath 查询如下所示:
(
//*[@ID=333]
/*[ count(*) > 2
and (
*[contains(., 'English')]
and *[contains(., 'French')]
and *[contains(., 'Chinese')]
)
]
/..
)[1]
如您所见,在其周围包裹更多 PHP 代码意义不大。
在这些最明显的点旁边,应该注意的是,信息作为具有三个值的数组比三个编号变量 ($infos = ["English", "French", "Chinese"];
) 更好。
示例:
$expr = sprintf("
(
//*[@ID=%d]
/*[ count(*) > 2
and (
*[contains(., %s)]
and *[contains(., %s)]
and *[contains(., %s)]
)
]
/..
)[1]",
$parentId, xpath_string($infos[0]), xpath_string($infos[1]), xpath_string($infos[2])
);
list($element) = $xml->xpath($expr) + [NULL];
if (empty($element)) {
// element not found
return;
}
// extend element
foreach ($record as $nodname => $val) {
$element->addChild($nodname, $val);
}
这给出了预期的结果:
<Article ID="333">
<author>John Silas</author>
<pubDate>01/01/2017</pubDate>
<Translations>
<lang1>English</lang1>
<lang2>French</lang2>
<lang3>Arab</lang3>
<lang3>Chinese</lang3>
</Translations>
<syntax>irrelevant</syntax><adjectives>None</adjectives><verbs>2</verbs><prepositions>5</prepositions></Article>