使用Perl进行XPath

时间:2012-08-21 16:40:40

标签: perl xpath

我在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地址中的“:”字符是否会影响代码?

1 个答案:

答案 0 :(得分:5)

您必须定义outcaccbc的含义,以便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
Value: 1234