1

我在 Window 7 机器上使用 Perl 进行编码。我可以使用下面的 XPath 代码从 XML 中提取数据

use strict;
use warning;

use XML::LibXML;

my $parser = XML::LibXML->new();
        my $doc    = $parser->parse_file($newfile);
        my $query  = "/tradenet/message/header/unique_ref_no/date/text( )";
        my($node)   = $doc->findnodes($query);
        $node->setData("$file_seq_number");  

但是,当我在不同的 XML 上使用相同的代码时,第二个文档的 xpath 如下所示:

/TradenetResponse/OutboundMessage/out:OutwardPermit/out:Declaration/out:Header/cac:UniqueReferenceNumber/cbc:SequenceNumeric

连同 Perl 代码,提取代码如下所示:

my $parser = XML::LibXML->new();
    my $doc    = $parser->parse_file($newfile);
    my $query  = "/TradenetResponse/OutboundMessage/out:OutwardPermit/out:Declaration/out:Header/cac:UniqueReferenceNumber/cbc:SequenceNumeric/text( )";
    my($node)   = $doc->findnodes($query);
    $node->setData("$file_seq_number");

使用第二个代码,我无法从第二个 XML 中检索数据。我收到此错误“无法在 Perl.pl 第 5 行的未定义值上调用方法“setData””。

第二个 XPATH 地址中的“:”字符会影响代码吗?

4

1 回答 1

5

您必须定义 what outcaccbcmean 以便 XPath 查询找到适当的节点:

my $doc = $parser->parse_file($newfile);
my $xpath_context = XML::LibXML::XPathContext->new($doc->documentElement());

# These URIs need to be the same as the ones in the source document
$xpath_context->registerNs('out', 'http://example.com/out.xsd');
$xpath_context->registerNs('cac', 'http://example.com/cac.xsd');
$xpath_context->registerNs('cbc', 'http://example.com/cbc.xsd');

my $query  = "/TradenetResponse/OutboundMessage/out:OutwardPermit/out:Declaration/out:Header/cac:UniqueReferenceNumber/cbc:SequenceNumeric/text( )";
my ($node) = $xpath_context->findnodes($query);

正如所承诺的,这是一个工作示例。一、测试输入文件:

<?xml version="1.0"?>

<!-- input.xml -->

<TradenetResponse xmlns:a="http://example.com/out.xsd"
                  xmlns:b="http://example.com/cac.xsd"
                  xmlns:c="http://example.com/cbc.xsd">
  <OutboundMessage>
    <a:OutwardPermit>
      <a:Declaration>
        <a:Header>
          <b:UniqueReferenceNumber>
            <c:SequenceNumeric>1234</c:SequenceNumeric>
          </b:UniqueReferenceNumber>
        </a:Header>
      </a:Declaration>
    </a:OutwardPermit>
  </OutboundMessage>
</TradenetResponse>

这是有效的 Perl 脚本:

#!/usr/bin/perl

# parse.pl

use strict;
use warnings;
use XML::LibXML;

my $parser = XML::LibXML->new();

my $newfile = "input.xml";
my $doc = $parser->parse_file($newfile);
my $xpath_context = XML::LibXML::XPathContext->new($doc->documentElement());

# These URIs need to be the same as the ones in the source document
$xpath_context->registerNs('out', 'http://example.com/out.xsd');
$xpath_context->registerNs('cac', 'http://example.com/cac.xsd');
$xpath_context->registerNs('cbc', 'http://example.com/cbc.xsd');

# Query wrapped for clarity                                                                                                         
my $query = "/TradenetResponse/OutboundMessage/out:OutwardPermit" .
            "/out:Declaration/out:Header/cac:UniqueReferenceNumber" .
            "/cbc:SequenceNumeric/text()";

my ($node) = $xpath_context->findnodes($query);

print "Value: " . $node->getData() . "\n";

我的输出是:

sean@localhost:~xmltest$ ./parse.pl
价值:1234
于 2012-08-21T17:02:37.697 回答