Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/14.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_Xml_Xpath - Fatal编程技术网

PHP xpath无法定位节点

PHP xpath无法定位节点,php,xml,xpath,Php,Xml,Xpath,给定以下片段: <svrl:failed-assert> <svrl:text>message</svrl:text> <svrl:diagnostic> <diag xmlns="example2.com"> <record> <record.01>141</record.01>

给定以下片段:

<svrl:failed-assert>
    <svrl:text>message</svrl:text>
        <svrl:diagnostic>
            <diag xmlns="example2.com">
                <record>
                    <record.01>141</record.01>
                </record>
            </diag>
        </svrl:diagnostic>
</svrl:failed-assert>
然后我循环遍历每一个并尝试查找子项:

foreach($errors as $error) {
     $text = $error->xpath('svrl:text'); //works fine
     $record = $error->xpath('svrl:diagnostic/diag/record'); //FAILS
}
无论我尝试使用何种组合,都无法使xpath表达式正确定位
diag
record
节点

我假设这可能与以下事实有关:子节点没有名称空间,而父节点没有名称空间。我无法控制源文档名称空间


是否可以使用xpath表达式定位有问题的节点?

您可以尝试类似的xpath表达式

svrl:diagnostic/*[namespace-uri()='example2.com' and local-name()='diag']/*[namespace-uri()='example2.com' and local-name()='record']
当然不是很漂亮,但应该可以完成这项工作。

使用以下方法:

//*[namespace-uri()='example2.com']/*[name()='record.01']/text()

处理xpath是XML最大的难题之一。除了痛苦之外,它也是一个极其缓慢的处理过程(比数组慢100倍)

在与xpath抗争多年后,我决定不再使用它,我将XML转换为Json以快速工作

取决于您需要什么,但您可能需要考虑这个选项。

用法:

$var = '<svrl:failed-assert>
<svrl:text>message</svrl:text>
    <svrl:diagnostic>
        <diag xmlns="example2.com">
            <record>
                <record.01>141</record.01>
            </record>
        </diag>
    </svrl:diagnostic>
</svrl:failed-assert>';

$result=xmlstr_to_array($var);
职能:

// load xml string
function xmlstr_to_array($xmlstr) {
    $doc = new DOMDocument();
    $doc->loadXML($xmlstr);
    return domnode_to_array($doc->documentElement);
}

// convert nodes
function domnode_to_array($node) {
$output = array();
switch ($node->nodeType) {
    case XML_CDATA_SECTION_NODE:
    case XML_TEXT_NODE:
        $output = trim($node->textContent);
        break;
    case XML_ELEMENT_NODE:
        for ($i = 0, $m = $node->childNodes->length; $i < $m; $i++) {
            $child = $node->childNodes->item($i);
            $v = domnode_to_array($child);
            if (isset($child->tagName)) {
                $t = ConvertTypes($child->tagName);
                if (!isset($output[$t])) {
                    $output[$t] = array();
                }
                $output[$t][] = $v;
            } elseif ($v) {
                $output = (string) $v;
            }
        }
        if (is_array($output)) {
            if ($node->attributes->length) {
                $a = array();
                foreach ($node->attributes as $attrName => $attrNode) {
                    $a[$attrName] = ConvertTypes($attrNode->value);
                }
                $output['@attributes'] = $a;
            }
            foreach ($output as $t => $v) {
                if (is_array($v) && count($v) == 1 && $t != '@attributes') {
                    $output[$t] = $v[0];
                }
            }
        }
        break;
}
return $output;
}

//convert types
function ConvertTypes($org) {
if (is_numeric($org)) {
    $val = floatval($org);
} else {
    if ($org === 'true') {
        $val = true;
    } else if ($org === 'false') {
        $val = false;
    } else {
        if ($org === '') {
            $val = null;
        } else {
            $val = $org;
        }
    }
}
return $val;
}
//加载xml字符串
函数xmlstr_to_数组($xmlstr){
$doc=新的DOMDocument();
$doc->loadXML($xmlstr);
将domnode_返回到_数组($doc->documentElement);
}
//转换节点
函数domnode_到_数组($node){
$output=array();
开关($node->nodeType){
案例XML\U CDATA\U节\U节点:
案例XML_文本_节点:
$output=trim($node->textContent);
打破
案例XML_元素_节点:
对于($i=0,$m=$node->childNodes->length;$i<$m;$i++){
$child=$node->childNodes->item($i);
$v=domnode_到_数组($child);
if(isset($child->tagName)){
$t=ConvertTypes($child->tagName);
如果(!isset($output[$t])){
$output[$t]=array();
}
$output[$t][]=$v;
}埃尔塞伊夫(五美元){
$output=(字符串)$v;
}
}
if(is_数组($output)){
如果($node->attributes->length){
$a=数组();
foreach($node->属性为$attrName=>$attrNode){
$a[$attrName]=ConvertTypes($attrNode->value);
}
$output['@attributes']=$a;
}
foreach($t=>v的输出){
if(is_数组($v)&&count($v)==1&&$t!='@attributes')){
$output[$t]=$v[0];
}
}
}
打破
}
返回$output;
}
//转换类型
函数类型($org){
如果(是数字($org)){
$val=floatval($org);
}否则{
如果($org=='true'){
$val=true;
}如果($org=='false',则为else){
$val=false;
}否则{
如果($org==''){
$val=null;
}否则{
$val=$org;
}
}
}
返回$val;
}

这是因为
diag
元素声明了默认名称空间,其中URI是
“example2.com”
。请注意,没有前缀的子元素隐式继承祖先的默认名称空间

您需要将前缀映射到默认命名空间,并使用前缀引用该命名空间中的元素:

foreach($errors as $error) 
{
     $error->registerXPathNamespace('foo', 'example2.com');
     $text = $error->xpath('svrl:text'); 
     $record = $error->xpath('svrl:diagnostic/foo:diag/foo:record');
}

谢谢你发布这个。虽然我可能更喜欢使用xpath(因为我已经在手头的解析工作中使用它),但我也更喜欢使用JSON对象,所以我将使用您的函数来跳转StartHanks。xpath肯定显示了它的弱点——直觉上,它肯定不是。这让我走了一半。我确实在寻找
节点的值,但现在我无法让xpath找到该节点,可能是因为
.triple
svrl:diagnostic/foo:diag/foo:record/foo:record.01
为我返回值
141
为我
$parent->xpath('svrl:diagnostic/foo:diag/foo:record/foo:record.01')
,其中,
$parent
是重复上下文,返回4个数组(表示record.01的4个外观),每个数组填充一个完全空的
SimpleXMLElement
数组([0]=>SimpleXMLElement对象())
// load xml string
function xmlstr_to_array($xmlstr) {
    $doc = new DOMDocument();
    $doc->loadXML($xmlstr);
    return domnode_to_array($doc->documentElement);
}

// convert nodes
function domnode_to_array($node) {
$output = array();
switch ($node->nodeType) {
    case XML_CDATA_SECTION_NODE:
    case XML_TEXT_NODE:
        $output = trim($node->textContent);
        break;
    case XML_ELEMENT_NODE:
        for ($i = 0, $m = $node->childNodes->length; $i < $m; $i++) {
            $child = $node->childNodes->item($i);
            $v = domnode_to_array($child);
            if (isset($child->tagName)) {
                $t = ConvertTypes($child->tagName);
                if (!isset($output[$t])) {
                    $output[$t] = array();
                }
                $output[$t][] = $v;
            } elseif ($v) {
                $output = (string) $v;
            }
        }
        if (is_array($output)) {
            if ($node->attributes->length) {
                $a = array();
                foreach ($node->attributes as $attrName => $attrNode) {
                    $a[$attrName] = ConvertTypes($attrNode->value);
                }
                $output['@attributes'] = $a;
            }
            foreach ($output as $t => $v) {
                if (is_array($v) && count($v) == 1 && $t != '@attributes') {
                    $output[$t] = $v[0];
                }
            }
        }
        break;
}
return $output;
}

//convert types
function ConvertTypes($org) {
if (is_numeric($org)) {
    $val = floatval($org);
} else {
    if ($org === 'true') {
        $val = true;
    } else if ($org === 'false') {
        $val = false;
    } else {
        if ($org === '') {
            $val = null;
        } else {
            $val = $org;
        }
    }
}
return $val;
}
foreach($errors as $error) 
{
     $error->registerXPathNamespace('foo', 'example2.com');
     $text = $error->xpath('svrl:text'); 
     $record = $error->xpath('svrl:diagnostic/foo:diag/foo:record');
}