【问题标题】:Extracting data from an XML document that uses namespaces从使用命名空间的 XML 文档中提取数据
【发布时间】:2016-01-27 00:35:27
【问题描述】:

我有一些 XML 文件,我想使用其中的一些信息。我已经编写了一个代码来读取这些文件,然后查找一些条件。

问题是这些 XML 文件以

开头
   <SquishReport version="2.1" xmlns="http://www.froglogic.com/XML2">

而 Perl 无法读取它们(至少在我的代码中!)。但是当我将这些行附加到XML 文件的第一行时

   <?xml version="1.0" encoding="UTF-8"?>
   <?xml-stylesheet type="text/xsl"?>

效果很好。

我的 XML 文件 test.xml 中的一些行:

<SquishReport version="2.1" xmlns="http://www.froglogic.com/XML2">
   <test name="TEST">
      <prolog time="2015-10-01T03:45:22+02:00"/>
      <test name="tst_start_app">
          <prolog time="2015-02-01T03:45:23+02:00"/>
          <message line="38" type="LOG" file="C:\squish\test\sources.py" time="2015-02-01T03:45:23+02:00">
              <description>
                <![CDATA[>>  >>  >> start: init (global) - testcase C:\squish\test\tst_start_app]]></description>
          </message>
       </test>
   </test>
</SquishReport>

读取 XML 文件的 Perl 代码是:

use strict;
use warnings;
use feature 'say';
use XML::LibXML;

# Parse the XML
my $xml = XML::LibXML->load_xml(location => 'test.xml');

# Iterate the entries
for my $entry ($xml->findnodes('/SquishReport/test/test')) {
    my $key = $entry->findvalue('@name');
    say "$key";
}

【问题讨论】:

标签: xml perl xml-libxml


【解决方案1】:

该文档的根节点是http://www.froglogic.com/XML2 命名空间中名称为SquishReport 的元素。简而言之,我们可以说根节点是一个

{http://www.froglogic.com/XML2}SquishReport


当在 XPath 中使用 SquishReport(而不是 prefix:SquishReport)时,它会尝试匹配在 null 命名空间中名称为 SquishReport 的元素。简而言之,我们可以说它试图匹配一个

{}SquishReport


要指定命名空间,可以使用context 中定义的前缀,如下所示:

use strict;
use warnings;
use feature qw( say );

use XML::LibXML               qw( );
use XML::LibXML::XPathContext qw( );

my $xpc = XML::LibXML::XPathContext->new();
$xpc->registerNs(sr => 'http://www.froglogic.com/XML2');

my $doc = XML::LibXML->load_xml( location => 'test.xml' );
for my $entry ($xpc->findnodes('/sr:SquishReport/sr:test/sr:test', $doc)) {
    my $key = $entry->findvalue('@name');
    say $key;
}


注意:XPath 中使用的前缀与 XML 文档中使用的前缀(如果有)无关。您应该知道要搜索的元素所在的命名空间,但不知道给定文档使用的前缀。

【讨论】:

  • 非常感谢您的出色回答!
  • 这个真的很干净很清晰!我倾向于使用由XML::LibXML 构建的模块,但在这里看起来很简单。 XML 永远不会消失,perl 有一些非常强大的工具来处理它。
【解决方案2】:

Perl 有这么多 优秀的 XML 工具 - 感谢所有模块开发人员和 libxml2,XML 似乎很容易。其中一个工具是XML::Dataset - 一个便利的“脚手架”模块,它建立在XML::LibXML 之上,并使用“配置文件”标记语言从 XML 源中获取数据(NB:配置文件标记对空格和行尾敏感)。

例如:

use XML::Dataset;
use DDP;

my $xml = "Squish.xml" ; 
open my $fh, "<", $xml or die "aiiieee!";
my $test_data = do { local $/; <$fh> };

# describe the data using XML::Dataset simplified markup:
my $data_profile
    = q(
          SquishReport
            test
              test
                 name = dataset:name);

# parse it with XML::Dataset profile
my $parsed_data = parse_using_profile($test_data, $data_profile);

# view the element with Data::Printer
foreach my $element ( $parsed_data->{name}){
     p $element ;
};

Squish.xml

<SquishReport version="2.1" xmlns="http://www.froglogic.com/XML2">
   <test name="TEST">
      <prolog time="2015-10-01T03:45:22+02:00"/>
      <test name="tst_start_app">
          <prolog time="2015-02-01T03:45:23+02:00"/>
          <message line="38" type="LOG" file="C:\squish\test\sources.py" time="2015-02-01T03:45:23+02:00">
              <description>
                <![CDATA[>>  >>  >> start: init (global) - testcase C:\squish\test\tst_start_app]]></description>
          </message>
       </test>
   </test>
</SquishReport>

输出:

\ [
    [0] {
        name   "tst_start_app"
    }
]

【讨论】:

    猜你喜欢
    • 2016-05-14
    • 1970-01-01
    • 2011-03-30
    • 1970-01-01
    • 1970-01-01
    • 2013-05-11
    • 2015-05-03
    • 1970-01-01
    • 2010-10-22
    相关资源
    最近更新 更多