我熟悉XML,并将其用于一些简单的用途。但是,我被要求创建一个自定义解决方案(必须使用Perl)来将付款提交给AuthorizeNet的网关。 AuthNet不支持Perl,所以我是独立的。XML :: LibXML和名称空间
我使用AuthNet的latest method,它依靠以XML格式发送和接收交易数据。
我设法使用Perl模块XML::LibXML成功提交和批准测试(沙箱)事务。
我试图解析返回数据时遇到了一个障碍。我终于明白,我是第一次处理命名空间。我得到的沙箱返回数据如下。
<createTransactionResponse
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd">
<refId />
<messages>
<resultCode>Ok</resultCode>
<message>
<code>I00001</code>
<text>Successful.</text>
</message>
</messages>
<transactionResponse>
<responseCode>1</responseCode>
<authCode>GTR92Q</authCode>
<avsResultCode>Y</avsResultCode>
<cvvResultCode>P</cvvResultCode>
<cavvResultCode>2</cavvResultCode>
<transId>40003699670</transId>
<refTransID />
<transHash>7E1148E18D5D0E0BE202EB1BCE4B0F09</transHash>
<testRequest>0</testRequest>
<accountNumber>XXXX1111</accountNumber>
<accountType>Visa</accountType>
<messages>
<message>
<code>1</code>
<description>This transaction has been approved.</description>
</message>
</messages>
<userFields>
<userField>
<name>MerchantDefinedFieldName1</name>
<value>MerchantDefinedFieldValue1</value>
</userField>
</userFields>
<transHashSha2 />
</transactionResponse>
</createTransactionResponse>
我需要从中提取某些值。我走,从AuthNet网关返回上述数据,将其存储在var $cont
,并准备:
my $dom = XML::LibXML->load_xml(string => $cont);
然后,我试图通过数据节点解析,搜索特定的值,例如:
foreach my $transres ($dom->findnodes("/createTransactionResponse/messages/message")) {
print "Message: " . $transres->to_literal() . "<br />\n";
}
这从不返回任何值。然后我意识到我正在处理命名空间问题。我试图注册的命名空间的许多变化,但无济于事,例如:
my $xpc = XML::LibXML::XPathContext->new($dom);
$xpc->registerNs("xsi", "http://www.w3.org/2001/XMLSchema-instance");
$xpc->registerNs("xsd", "http://www.w3.org/2001/XMLSchema");
foreach my $transres ($xpc->findnodes("//xsi:resultCode")) {
print "Result: " . $transres->to_literal() . "<br />\n";
}
这一切只是铸造一下,希望能对某种结果。我注意到,尽管返回数据引用了多个名称空间,但其余数据中的任何一个实际上都没有使用它们。我在XML命名空间问题上发现了一些StackOverflow响应,但是我永远无法找到如何在XML数据中的其他地方未使用指定名称空间时引用节点的示例。比如,什么是默认的(如果你会的话)命名空间引用来使用,当没有命名空间被引用时 ......如果这是有道理的。
我遇到了一个entry elsewhere in StackOverflow,其中它提到使用允许忽略名称空间的“本地名称”函数。我认为这可能会绕过这个问题,当我尝试它时,我终于看到了一些数据显示。
foreach my $transres ($dom->findnodes("//*[local-name()='resultCode']")) {
print "Result: " . $transres->to_literal() . "<br />\n";
}
这导致所需/期望值“Ok”的返回。它也适用于迄今我尝试过的其他节点。但是,我通常不愿意使用“只是忽略它”类型的解决方案,除非它们是真正合适的并且需要。
我的问题归结为这个问题:我使用的bypass-namespace方法是否最终从返回的XML数据中获取数据是可取的?
我想知道为什么AuthNet在返回数据中指定了多个名称空间,然后在数据中不使用它们 - 至少是我当前回收的数据。如果我绕过代码中的命名空间,但后来又如何,特别是当我们开始运行时,不同的命名空间会变得相关?我其实并不知道,AuthNet所谓的“支持”我已经能够达到的范围从无益到完全没有反应。
任何有关Perl/XML /名称空间问题经验丰富的建议/指导将不胜感激。
是的! @Borodin,那些是我正在寻找的提示。您在命名空间问题上的说明有所不同,并帮助我解决了这个问题。我现在有一些工作代码可以成功解析AuthNet返回数据。 – user2226161