从使用命名空间的 XML 文档中提取数据
Extracting data from an XML document that uses namespaces
我有一些 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";
}
该文档的根节点是 http://www.froglogic.com/XML2
命名空间中名称为 SquishReport
的元素。简而言之,我们可以说根节点是 a
{http://www.froglogic.com/XML2}SquishReport
当在 XPath 中使用 SquishReport
(而不是 prefix:SquishReport
)时,它会尝试匹配空命名空间中名称为 SquishReport
的元素.简而言之,我们可以说它试图匹配 a
{}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 文档(如果有)中使用的前缀无关。您应该知道您要搜索的元素所在的命名空间,但不知道给定文档使用的前缀。
Perl 有 这么多 优秀的 XML 工具 - 感谢所有模块开发人员和 libxml2
, XML almost seems easy. One of those tools is XML::Dataset
- 一个方便的 "scaffolding" 构建模块在 XML::LibXML
上并使用 "profile" 标记语言从 XML 来源获取数据(注意: 配置文件标记对空格和行敏感结局)。
例如:
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"
}
]
我有一些 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";
}
该文档的根节点是 http://www.froglogic.com/XML2
命名空间中名称为 SquishReport
的元素。简而言之,我们可以说根节点是 a
{http://www.froglogic.com/XML2}SquishReport
当在 XPath 中使用 SquishReport
(而不是 prefix:SquishReport
)时,它会尝试匹配空命名空间中名称为 SquishReport
的元素.简而言之,我们可以说它试图匹配 a
{}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 文档(如果有)中使用的前缀无关。您应该知道您要搜索的元素所在的命名空间,但不知道给定文档使用的前缀。
Perl 有 这么多 优秀的 XML 工具 - 感谢所有模块开发人员和 libxml2
, XML almost seems easy. One of those tools is XML::Dataset
- 一个方便的 "scaffolding" 构建模块在 XML::LibXML
上并使用 "profile" 标记语言从 XML 来源获取数据(注意: 配置文件标记对空格和行敏感结局)。
例如:
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"
}
]