我正在使用 perl 的 XML::LibXML 模块来解析来自设备的 XML 响应。
看来,我可以成功获取数据的唯一方法是修改来自设备的 XML 响应。
这是我从设备发出的 XML 响应:
<chassis-inventory xmlns="http://xml.juniper.net/junos/10.3D0/junos-chassis">
<chassis junosstyle="inventory">
<name>Chassis</name>
<serial-number>JN111863EAFF</serial-number>
<description>VJX1000</description>
<chassis-module>
<name>Midplane</name>
</chassis-module>
<chassis-module>
<name>System IO</name>
</chassis-module>
<chassis-module>
<name>Routing Engine</name>
<description>VJX1000</description>
<chassis-re-disk-module>
<name>ad0</name>
<disk-size>1953</disk-size>
<model>QEMU HARDDISK</model>
<serial-number>QM00001</serial-number>
<description>Hard Disk</description>
</chassis-re-disk-module>
</chassis-module>
<chassis-module>
<name>FPC 0</name>
<chassis-sub-module>
<name>PIC 0</name>
</chassis-sub-module>
</chassis-module>
<chassis-module>
<name>Power Supply 0</name>
</chassis-module>
</chassis>
</chassis-inventory>
这是我用来解析和查找序列号的 perl 代码,例如:
#!/bin/env perl
use strict;
use warnings;
use XML::LibXML;
my $f = ("/var/working/xmlstuff");
sub yeah {
my $ff;
my $f = shift;
open(my $fff,$f);
while(<$fff>) {
$_ =~ s/^\s+$//;
$_ =~ s/^(<\S+)\s.*?=.*?((?:\/)?>)/$1$2/g;
$ff .= $_;
}
close($fff);
return $ff
}
my $tparse = XML::LibXML->new();
my $ss = $tparse->load_xml( string => &yeah($f));
print map $_->to_literal,$ss->findnodes('/chassis-inventory/chassis/serial-number');
如果我不使用正则表达式替换,则不会加载任何脚本来解析。
我可以理解换行符的去除,但是为什么我必须从 XML 响应中删除属性,所以它只在以下行时才有效:
<chassis-inventory xmlns="http://xml.juniper.net/junos/10.3D0/junos-chassis">
<chassis junosstyle="inventory">
变成这样:
<chassis-inventory>
<chassis>
谢谢您的帮助。
最佳答案
您的 XPATH 表达式失败的原因是 namespace ;你需要在上下文中搜索。这是来自 XML::libXML documentation 的解释:
NOTE ON NAMESPACES AND XPATH:
A common mistake about XPath is to assume that node tests consisting of an element name with no prefix match elements in the default namespace. This assumption is wrong - by XPath specification, such node tests can only match elements that are in no (i.e. null) namespace.
So, for example, one cannot match the root element of an XHTML document with $node->find('/html') since '/html' would only match if the root element had no namespace, but all XHTML elements belong to the namespace http://www.w3.org/1999/xhtml. (Note that xmlns="..." namespace declarations can also be specified in a DTD, which makes the situation even worse, since the XML document looks as if there was no default namespace).
为了解决这个问题,注册命名空间,然后使用命名空间搜索你的文档。这是一个适合您的示例:
#!/bin/env perl
use strict;
use warnings;
use XML::LibXML;
my $xml = XML::LibXML->load_xml( location => '/var/working/xmlstuff');
my $xpc = XML::LibXML::XPathContext->new($xml);
$xpc->registerNs('x', 'http://xml.juniper.net/junos/10.3D0/junos-chassis');
foreach my $node ($xpc->findnodes('/x:chassis-inventory/x:chassis/x:serial-number')) {
print $node->textContent() . "\n";
}
关于perl - 使用 perl XML::LibXML 解析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7041719/