perl - 使用 perl XML::LibXML 解析

标签 perl libxml2

我正在使用 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>
  • 这是 XML 响应还是 XML::LibXML 模块的问题?
  • 有没有办法让它忽略文件中有空行而不使用正则表达式替换的事实?

  • 谢谢您的帮助。

    最佳答案

    您的 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/

    相关文章:

    perl - 如何验证(或转义)用户的姓名字段,以免破坏我的电子邮件发送软件?

    perl - 在 Perl 中向 PayMill 发送 CURL 请求

    perl - 在 Perl 变量中使用十六进制值

    perl - 在 Perl 中启动非等待后台进程

    iphone - libxml2 示例(带有包装器)

    xml - 如何在片段创建中使用全局命名空间定义?

    linux - 如何正确运行 Perl "one liner"命令行脚本?

    html - 我们可以使用正则表达式使用 libxml2 查找具有特定属性值的所有节点吗?

    memory-management - libXML:检查节点是否已经取消链接并释放