【问题标题】:php xpath problemsphp xpath 问题
【发布时间】:2011-02-21 02:11:34
【问题描述】:

我正在执行 cURL POST 并返回错误响应,将其解析为数组,但现在 xpath 出现问题。

// XML

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<errors xmlns="http://host/project">
   <error code="30" description="[] is not a valid email address."/>
   <error code="12" description="id[] does not exist."/>
   <error code="3" description="account[] does not exist."/>
   <error code="400" description="phone[] does not exist."/>
</errors>

// 函数/类

class parseXML
{
    protected $xml;

    public function __construct($xml) {
        if(is_file($xml)) {
            $this->xml = simplexml_load_file($xml);
        } else {
            $this->xml = simplexml_load_string($xml);
        }
    }

    public function getErrorMessage() {
        $in_arr = false;
        $el = $this->xml->xpath("//@errors");        
        $returned_errors = count($el);

        if($returned_errors > 0) {
            foreach($el as $element) {
                if(is_object($element) || is_array($element)) {
                    foreach($element as $item) {
                        $in_arr[] = $item;
                    }
                }
            }
        } else {
            return $returned_errors;
        }            
        return $in_arr;
    }
}

//调用函数

// $errorMessage is holding the XML value in an array index
// something like: $arr[3] = $xml;
$errMsg = new parseXML($arr[3]); 
$errMsgArr = $errMsg->getErrorMessage();

我想要的是所有的错误代码和描述属性值

编辑:

好的,这是 print_r($this->xml,true);

SimpleXMLElement Object
(
    [error] => Array
        (
            [0] => SimpleXMLElement Object
                (
                    [@attributes] => Array
                        (
                            [code] => 30
                            [description] => [] is not a valid email address.
                        )

                )

            [1] => SimpleXMLElement Object
                (
                    [@attributes] => Array
                        (
                            [code] => 12
                            [description] => Id[12345] does not exist.
                        )

                )

            [2] => SimpleXMLElement Object
                (
                    [@attributes] => Array
                        (
                            [code] => 3
                            [description] => account[] does not exist.
                        )

                )

            [3] => SimpleXMLElement Object
                (
                    [@attributes] => Array
                        (
                            [code] => 400
                            [description] => phone[] does not exist.
                        )

                )

        )

)

对于我的一生,我无法弄清楚为什么我可以获得代码和描述,有什么想法吗?

编辑 #2 好的,我想我会分解它。

我正在使用 cURL 向我们的一台服务器发布请求,我解析出 HTTP 响应标头和 xml(如果返回了 xml)。 header/xml 中的每一行我都分解成一个数组。因此,如果出现错误,我会看到数组的额外索引。然后我做这样的事情。

$if_err_from_header = $http_return_response[10]; 
// I know that index 10 is where if any the error message in xml is (the one posted above).

之后我会这样做:

$errMsg = new parseXML($if_err_from_header); 
$errMsgArr = $errMsg->getErrorMessage();

我仍然无法从错误的属性中获取代码和描述,我错过了什么?

编辑 #3 好的,为什么这行得通?

$in_arr = false;
// This returns all the code attributes
$el = $this->xml->xpath("//@code");

# if $el is false, nothing returned from xpath(), set to an empty array
$el = $el == false ? array() : $el;

foreach($el as $element) {
    $in_arr[] = array("code" => $element["code"], "description" => $element["description"]);
}
return $in_arr;

编辑#4:

好的,这得到了我想要的值,但它有点像 hack,想选择特定的元素但是......

$el = $this->xml->xpath("//*");

【问题讨论】:

    标签: php xml xpath parsing


    【解决方案1】:

    确保考虑到命名空间:

    $this->xml->registerXPathNamespace('n', 'http://host/project');
    $el = $this->xml->xpath("/n:errors/n:error");
    $returned_errors = count($el);
    

    以及访问较低值的示例..

    foreach($el as $element) {
       print "code: " . $element["code"] . "\n";
    }
    

    【讨论】:

    • 所以只是为了澄清 n 是用于命名空间的变量还是命名空间的名称?所以我有 xmlns,我会使用那个还是 n?
    • @Phil,您已将“host/project”定义为默认命名空间,我们选择将前缀“n”与其关联。如果不指定此命名空间,PHP 会尝试使用 null 命名空间,因此 XPath 表达式将返回一个空集。作为一个实验,创建一个新的错误节点,并将 xmlns 属性设置为“example”。您会看到它没有与其他人一起在输出中返回。
    • 添加了 SimpleXMLElement 对象是如何通过的,有什么想法吗?
    • 我猜是因为这些元素中的每一个($element 在你的例子中)都是一个对象,而不是一个数组。您是否使用 foreach() 尝试了我示例的第二部分?您应该能够使用 $element["code"]$element["description"] 而不是创建另一个循环。
    • 我试过你的代码非常好,但仍然返回一个空数组。我还有其他几个使用 xpath 的功能,并且所有功能都可以顺利运行。但是对于我的生活,我无法弄清楚为什么这个对象没有。请参阅编辑#2
    【解决方案2】:
    XPath 中的

    @ 是属性选择器。您正在尝试选择根元素,因此它应该是:

      $el = $this->xml->xpath("/errors");
    

    如果要选择所有错误元素,请使用

      $el = $this->xml->xpath("/errors/error");
    

      $el = $this->xml->xpath("//error");
    

    【讨论】:

    • 嗯仍然无法正常工作,但感谢您指出我使用的是属性选择器
    • 如果我只是传递数组索引我得到一个错误,这是由于索引不是一个字符串。如果我将索引转换为字符串,我会得到 0,因为 xpath 什么也没找到。有什么想法吗?
    • 添加了 SimpleXMLElement 对象是如何通过的,有什么想法吗?
    猜你喜欢
    • 2010-10-07
    • 1970-01-01
    • 2020-10-24
    • 2010-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-31
    相关资源
    最近更新 更多