首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >对成员函数setAttribute的Xpath setAttribute致命错误调用

对成员函数setAttribute的Xpath setAttribute致命错误调用
EN

Stack Overflow用户
提问于 2013-01-15 04:42:44
回答 3查看 1.5K关注 0票数 2

我正在记录来自API调用的错误请求/响应。为了在数据库中存储日志,我想用*替换信用卡号。

请求XML如下所示:

代码语言:javascript
复制
<xml>
    <request servicekey="service key" branchcode="branch" language="EN" postalcode="Postal Code" country="CA" email="email@example.com">
        <paxes>
            <pax id="1" birthdate="19790215" firstname="John" lastname="Smith" />
            <pax id="2" birthdate="19800828" firstname="Jane" lastname="Smith" />
        </paxes>
        <plans>
            <plan code="Plan Code" >
                <paxes>
                    <pax id="1" sumins="1200.00" />
                    <pax id="2" sumins="1480.31" />
                </paxes>
            </plan>
        </plans>
        <payments>
            <payment amount="246.24" type="VI" ccnum="4111111111111111" ccexp="0711" ccname="John Smith" />
        </payments>
    </request>
</xml>

在这里,我只需获取payment节点和ccnum属性来编辑它( xml保存为$requestXML):

代码语言:javascript
复制
$_req = new DOMDocument();
$_req->loadXML($requestXML);
$_xpathReq = new DOMXPath($_req);
$_reqDom = $_xpathReq->query("/xml/request/payments/payment");
$_reqDom->item(0)->setAttribute('ccnum','*****');
$requestXML = $_req->saveXML();    

它按预期工作,xml中的CC号被替换为*

$responseXML稍有不同:

代码语言:javascript
复制
<string xmlns="http://tempuri.org/">
    <xml>
        <request servicekey="service key" branchcode="branch code" language="EN" postalcode="Postal Code" country="CA" email="email@example.com">
            <paxes>
                <pax id="1" birthdate="19790215" firstname="John" lastname="Smith" />
                <pax id="2" birthdate="19800828" firstname="Jane" lastname="Smith" />
            </paxes>
            <plans>
                <plan code="Plan Code">
                    <paxes>
                        <pax id="1" sumins="1200.00" />
                        <pax id="2" sumins="1480.31" />
                    </paxes>
                </plan>
            </plans>
            <payments>
                <payment amount="246.24" type="VI" ccnum="4111111111111111" ccexp="0711" ccname="John Smith" />
            </payments>
        </request>
        <response>
            <errors>
                <error>Purchase Card Processing was not approved [-1]:Cancelled: null | CARD: **** | Exp: 1407 | Amount: $246.24</error>
            </errors>
        </response>
    </xml>
</string>

和前面一样,我运行一段非常相似的PHP代码:

代码语言:javascript
复制
$_req = new DOMDocument();
    $_req->loadXML($responseXML);
    $_xpathReq = new DOMXPath($_req);
    $_reqDom = $_xpathReq->query("/string/xml/request/payments/payment");
    $_reqDom->item(0)->setAttribute('ccnum','*****');
    $responseXML = $_req->saveXML(); 

但是当我运行这段代码时,我得到了指向包含$_reqDom->item(0)->setAttribute('ccnum','*****');的行的Fatal error: Call to a member function setAttribute() on a non-object

这两个xml之间的唯一区别是一个包含在string节点中,并且有一个额外的节点表示响应。我想我可以解决这个问题(只需取出response节点并将其附加到请求xml中),但我现在的任务就是以这种方式工作。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-01-15 05:22:00

这个问题是由于响应xml中的名称空间造成的。您必须将rootNamespace注册到XPath selector.The,以下代码将会起作用:

代码语言:javascript
复制
$response = new DOMDocument();
$response->loadXML($responseXml);
$selector = new DOMXPath($response);

// get the root namespace
$rootNamespace = $response->lookupNamespaceUri(
    $response->namespaceURI
);
// and register it with $selector. I'm using 'x' as the prefix
// you are free to use a different prefix
$selector->registerNamespace('x', $rootNamespace);

// You won't need to specify the whole path. You could just grab 
// all payment node regardless of their location in the xml tree
$result = $selector->query('//x:payment');
foreach($result as $node) {
    $node->setAttribute('ccnum', '*****');
}

$responseXml = $response->saveXML();
echo $responseXml;
票数 2
EN

Stack Overflow用户

发布于 2013-01-15 05:21:50

<string>标记包含一个名称空间,您需要向DOMXPath注册该名称空间。

代码语言:javascript
复制
$_req = new DOMDocument();
$_req->loadXML($responseXML);
$_xpathReq = new DOMXPath($_req);

$_xmlns = $_req->lookupNamespaceUri(NULL); 
$_xpathReq->registerNamespace('x', $_xmlns); 

$_reqDom = $_xpathReq->query("//x:xml/x:request/x:payments/x:payment");
$_reqDom->item(0)->setAttribute('ccnum','*****');
$responseXML = $_req->saveXML(); 
票数 1
EN

Stack Overflow用户

发布于 2016-06-09 03:58:46

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
  <feed xmlns="http://www.w3.org/2005/Atom" 
        xmlns:dc="http://purl.org/dc/elements/1.1/" 
        xmlns:dcterms="http://purl.org/dc/terms/" 
        xmlns:media="http://search.yahoo.com/mrss/" 
        xmlns:xhtml="http://www.w3.org/1999/xhtml">

这使得不可能进行DOMXPath查询。

代码语言:javascript
复制
libxml_use_internal_errors(true);
$doc->loadHTML($rawXml, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD | LIBXML_NSCLEAN);
libxml_use_internal_errors(false);

我希望这对某些人有帮助。用这个把我的头发扯下来。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14326300

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档