2017-06-15 104 views
1

有这样的XML文件 - t.xmlXML ::的libxml - XPath的 - 命名空间

<?xml version="1.0"?> 
<ArrayOfFiles xmlns="Our.Files" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> 
     <File> 
       <DownloadCount>1</DownloadCount> 
       <Id>11</Id> 
     </File> 
     <File> 
       <DownloadCount>2</DownloadCount> 
       <Id>22</Id> 
     </File> 
</ArrayOfFiles> 

xmlns声明是无效的,则xmlstarlet抱怨它,例如使用:

xmlstarlet sel -t -v "//File/Id" t.xml 

打印

t.xml:2.32: xmlns: URI Our.Files is not absolute 
<ArrayOfFiles xmlns="Our.Files" xmlns:i="http://www.w3.org/2001/XMLSchema-instan 

可能是出于同样的原因,我不能得到工作,下面的Perl代码太:

use 5.014; 
use warnings; 
use XML::LibXML; 

my $dom = XML::LibXML->new->parse_file('t.xml'); 
my $res = $dom->findnodes('//File/Id'); 
say $_->textContent for $res->get_nodelist; 

当我省略了xmlns声明,例如试图解析该修改的XML文件

<?xml version="1.0"?> 
<ArrayOfFiles> 
    <File> 
     <DownloadCount>1</DownloadCount> 
     <Id>11</Id> 
    </File> 
    <File> 
     <DownloadCount>2</DownloadCount> 
     <Id>22</Id> 
    </File> 
</ArrayOfFiles> 

上面的代码DWIM - 和打印:

11 
22 

的问题是,如何解析原始的XML文件,因为它是从外部下载网站 - 所以我必须处理它有点...

回答

6

这只是一个警告。使用XML名称空间时,请使用XML::LibXML::XPathContext

#!/usr/bin/perl 
use warnings; 
use strict; 
use feature qw{ say }; 

use XML::LibXML; 
use XML::LibXML::XPathContext; 


my $dom = 'XML::LibXML'->load_xml(location => shift); 

my $xpc = 'XML::LibXML::XPathContext'->new($dom); 
$xpc->registerNs(o => 'Our.Files'); 

my $res = $xpc->findnodes('//o:File/o:Id'); 
say $_->textContent for $res->get_nodelist; 
+0

是的!!!这正是我需要的!我正在阅读文档,并看到命名空间相关的警告(在更多地方),但老实说 - 绝对不懂如何使用它。 :) 非常非常感谢你。 – kobame

+0

hmm ..想知道为什么你用引用的''XML :: LibXML' - >加载'而不是普通的'XML :: LibXML->加载' - 但这应该是另一个问题... :) – kobame

+0

@kobame请参阅[调用类方法](https://perldoc.perl.org/perlobj.html#Invoking-Class-Methods)...它强制在'XML :: LibXML :: XPathContext'中调用'new',即使在范围内有一个函数'XML :: LibXML :: XPathContext' ...我从来没有被这个东西咬过,所以我从来没有使用它,但它确实确保在那个角落情况下的正确行为。 –