Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php xpath让我失望了_Php_Xpath - Fatal编程技术网

Php xpath让我失望了

Php xpath让我失望了,php,xpath,Php,Xpath,我有一个xml结构: 彼得·保罗 01/01/2015 英语 法语 阿拉伯的 中国人 猴米 01/01/2016 英语 约翰·塞拉斯 01/01/2017 英语 法语 阿拉伯的 中国人 我创建了一个AddRecordByInfoMatch()方法,该方法尝试 将新节点添加到任意给定ID的任意位置 当匹配存在时: function AddRecordByInfoMatch($ParentID, $Info_1, $Info_2, $Info_3, array $Record){

我有一个xml结构:


彼得·保罗
01/01/2015  
英语
法语
阿拉伯的
中国人
猴米
01/01/2016  
英语
约翰·塞拉斯
01/01/2017  
英语
法语
阿拉伯的
中国人
我创建了一个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 
        ));
不幸的是,输出;显示时,将新记录添加到项目中 ID为111的用户提供:

。。。
彼得·保罗
01/01/2015  
英语
法语
阿拉伯的
中国人
无关的
没有一个
2.
5.
...
我希望它在ID333的文章节点中,而 我在函数调用中指定了。我在xpath表达式中做错了什么??或者如何 我能做到这一点吗?任何帮助都将受到高度重视。祝大家新年快乐

我在xpath表达式中做错了什么

我可以发现的一个错误是(当用户在这里询问xpath的PHP标记下的Stackoverflow时很常见),您没有意识到脚本中可能存在的xpath注入

因此,对于我将给出的PHP示例,我将确保它的安全性,所使用的函数取自其中,其中也包含有关该主题的更多信息

除了这个(常见的)错误之外,直接出现在视图中的是,您可以在这里做很多事情,而您可以只使用一个XPath表达式来表达它

您希望第一个元素具有特定值的ID属性,然后包含一个子元素,该子元素至少包含三个子元素,其中三个子元素必须包含三分之一的文本

对于333的示例ID和三个示例文本“英语”、“法语”和“汉语”,XPath查询如下所示:

(
    //*[@ID=333]
        /*[ count(*) > 2
            and (
                *[contains(., 'English')]
                and *[contains(., 'French')]
                and *[contains(., 'Chinese')]
            )
        ]
    /..
)[1]
正如您所看到的,围绕它包装更多的PHP代码并没有多大意义

除了这些最明显的点之外,应该注意的是,infos作为一个具有三个值的数组比三个编号变量更好(
$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>

约翰·塞拉斯
01/01/2017
英语
法语
阿拉伯的
中国人
无关的

$data=$result->xpath($query)
$data=$xml->xpath($query)问题在第二个xpath中。它为整个xml文档选择法语、英语等,而不是为id为333的所选元素。就像@smarber说的。在$result上执行查询。Xpath也正在执行与标题相关的工作。这种情况下,显示器和椅背之间的错误都是按照命令完成的,仍然是一样的垃圾!非常感谢@hakre。虽然我用了另一种方法来解决这个问题,但我喜欢你的风格。它工作得完美无缺。再次感谢您。@OsagieOdigie:如果您喜欢,请随意对答案进行投票:-谢谢您的反馈!没什么大不了的,我采用的唯一解决方案是将xml转换成数组,因为当采用数组格式时,我可以轻松地操作节点。谢谢@hakre,尽管你的方法也很有效。