用Perl解析XML文档
我有一个奇怪的XML文档,按照以下方式排列用Perl解析XML文档,perl,xml-parsing,Perl,Xml Parsing,我有一个奇怪的XML文档,按照以下方式排列 <a> <b> <c c1="blah" c2="blah"> <d d1="blah0" d2="blah1" d3="blah2" d4="blah3" d5="blah4" /> <d d1="blah5" d2="blah6" d3="blah7" d4="blah8" d5="blah9" /> <d d1="bl
<a>
<b>
<c c1="blah" c2="blah">
<d d1="blah0" d2="blah1" d3="blah2" d4="blah3" d5="blah4" />
<d d1="blah5" d2="blah6" d3="blah7" d4="blah8" d5="blah9" />
<d d1="blah10" d2="blah11" d3="blah12" d4="blah13" d5="blah14" />
</c>
<c c1="blahc" c2="blah">
<d d1="blah0" d2="blah1" d3="blah2" d4="blah3" d5="blah4" />
<d d1="blah5" d2="blah6" d3="blah7" d4="blah8" d5="blah9" />
<d d1="blah10" d2="blah11" d3="blah12" d4="blah13" d5="blah14" />
</c>
...
<b>
....
</b>
<e/>
</a>
,在数组引用方面遇到了很多困难。
我尝试使用,但考虑到我的XML文件大小为500MB,它似乎不是一个好的选择。请推荐一种好的方法,因为我是Perl新手。您的问题有点让人困惑,您想要的是d
元素的属性,而不是c
元素的属性。或者,无论c
下的元素是什么,您都需要属性的值
在任何情况下,尤其是当文件很大时,这看起来很适合:
#/usr/bin/perl
严格使用;
使用警告;
使用XML::Twig;
XML::Twig->new(Twig\u处理程序=>{'b/c/*'=>\&get\u atts})
->解析(\*数据);#替换为parsefile('my.xml')
分包合同
{my($t,$elt)=@;
每个我的$att(qw(d2 d4 d5))
{打印“$att:”,$elt->att($att),”;}
打印“\n”;
$t->purge;#这将释放内存,因此最多保留1个d元素
}
__资料__
如果属性总是在d
元素中,请将'b/c/*'
替换为'b/c/d'
,这样效率会更高。您的问题有点混乱,您想要d
元素的属性,而不是c
元素的属性。或者,无论c
下的元素是什么,您都需要属性的值
在任何情况下,尤其是当文件很大时,这看起来很适合:
#/usr/bin/perl
严格使用;
使用警告;
使用XML::Twig;
XML::Twig->new(Twig\u处理程序=>{'b/c/*'=>\&get\u atts})
->解析(\*数据);#替换为parsefile('my.xml')
分包合同
{my($t,$elt)=@;
每个我的$att(qw(d2 d4 d5))
{打印“$att:”,$elt->att($att),”;}
打印“\n”;
$t->purge;#这将释放内存,因此最多保留1个d元素
}
__资料__
如果属性始终位于d
元素中,请将'b/c/*'
替换为'b/c/d'
,这样效率更高。使用:
更新:(对于mirod):使用来自Perl的XML::XSH2不那么优雅,但仍然可以工作-
#!/usr/bin/perl
use strict;
use warnings;
use XML::XSH2;
xsh q{
open 1.xml ;
for /a/b/c/d {
for my $attr in (@d2 | @d4 | @d5) {
perl { push @ar, $attr }
}
}
};
printf "%s:%s\n", $_->name, $_->value for @XML::XSH2::Map::ar;
或者,让Perl为您编写xsh代码:
#!/usr/bin/perl
use warnings;
use strict;
use XML::XSH2;
xsh 'open 1.xml';
xsh '$attributes = (' . join('|', map 'a/b/c/@d' . $_, 1, 2, 4) . ')';
for (@$XML::XSH2::Map::attributes) {
print $_->name, '=', $_->value, "\n";
}
使用:
更新:(对于mirod):使用来自Perl的XML::XSH2不那么优雅,但仍然可以工作-
#!/usr/bin/perl
use strict;
use warnings;
use XML::XSH2;
xsh q{
open 1.xml ;
for /a/b/c/d {
for my $attr in (@d2 | @d4 | @d5) {
perl { push @ar, $attr }
}
}
};
printf "%s:%s\n", $_->name, $_->value for @XML::XSH2::Map::ar;
或者,让Perl为您编写xsh代码:
#!/usr/bin/perl
use warnings;
use strict;
use XML::XSH2;
xsh 'open 1.xml';
xsh '$attributes = (' . join('|', map 'a/b/c/@d' . $_, 1, 2, 4) . ')';
for (@$XML::XSH2::Map::attributes) {
print $_->name, '=', $_->value, "\n";
}
CPAN中有许多XML模块可以帮助您实现这一点,但在本例中,我的重点是,它允许您简洁地描述要从XML中提取的数据
此程序使用示例数据并提供我认为您需要的输出(尽管严格来说,任何
节点都没有d=“xx”
属性)
使用严格;
使用警告;
使用特征“说”;
使用XML::XPath;
我的$xml=xml::XPath->new(ioref=>\*数据);
对于我的$cnode($xml->find('//b/c/d')->get\u nodelist){
对于($cnode->find('@d2 |@d4 |@d5')->get_nodelist){
打印$->getData,“\n”;
}
}
__资料__
...
输出
blah1
废话
废话
废话
废话
废话
废话11
废话13
废话14
胡说八道
废话
废话
废话
废话
废话
废话11
废话13
废话14
CPAN中有许多XML模块可以帮助您实现这一点,但在本例中,我的钱就在上面,它允许您简洁地描述要从XML中提取的数据
此程序使用示例数据并提供我认为您需要的输出(尽管严格来说,任何
节点都没有d=“xx”
属性)
使用严格;
使用警告;
使用特征“说”;
使用XML::XPath;
我的$xml=xml::XPath->new(ioref=>\*数据);
对于我的$cnode($xml->find('//b/c/d')->get\u nodelist){
对于($cnode->find('@d2 |@d4 |@d5')->get_nodelist){
打印$->getData,“\n”;
}
}
__资料__
...
输出
blah1
废话
废话
废话
废话
废话
废话11
废话13
废话14
胡说八道
废话
废话
废话
废话
废话
废话11
废话13
废话14
能否更具体地说明XML::Simple的问题?在某些XML文件中,“b”节点为空,这意味着每次处理此类XML文件时都会出现数组引用错误。您可以在尝试访问它之前添加条件;执行if(defined{path to node}){do which}500MB对于当前机器来说不是很多内存中的数据,因此XML::DOM将是一个有效的选择。主要的选择实际上取决于您是喜欢DOM
还是XPath
,还是喜欢XML::Twig等非标准的东西。顺便问一下,“请推荐一个好的方法,因为我是Perl新手”,您是在建议我们应该为有经验的Perl程序员保留我们糟糕的建议吗?!您能否更具体地说明XML::Simple的问题?在某些XML文件中,“b”节点为空,这意味着每次处理此类XML文件时都会出现数组引用错误。您可以在尝试访问它之前添加一个条件;执行if(defined{path to node}){do which}500MB对于当前机器来说不是很多内存中的数据,因此XML::DOM将是一个有效的选择。主要的选择实际上取决于您是喜欢DOM
还是XPath
,还是喜欢XML::Twig等非标准的东西。顺便问一下,“请推荐一个好的方法,因为我是Perl新手”,您是在建议我们应该为有经验的Perl程序员保留我们糟糕的建议吗?!我经常看到你的答案使用xsh。它们通常非常优雅。但是,从代码中使用xsh有多容易?通常情况下,目标不仅仅是打印结果,而是做一些工作