我需要从XML文件中读取行并将它们解析为字段。一行被定义为以<开头的文本。并以/>结尾它可以是由CR / LF分隔的单行或多行。这是一个典型的行:
<Label Name="lblIncidentTypeContent" Increasable="true" Left="140" Top="60"
Width="146 SpeechField="IncidentType_V" TextAlign="MiddleLeft" WidthPixel="-180"
WidthPercent="50" />
一旦我读完了这一行,我就需要将其解析为名称,左边,宽度等字段。然后,我想以特定的顺序输出带有数据的CSV。然后阅读下一行,直到EOF。
自从我做Perl(或任何其他类型的)编程以来已经很长时间了。欢迎任何帮助。
答案 0 :(得分:3)
不要将XML视为基于行的数据,因为它不是。相反,使用一个好的XML解析器,Perl有很多。
不要使用XML :: Simple!
其own documentation表示已弃用:
不鼓励在新代码中使用此模块。其他模块可用,提供更直接和一致的接口。特别强烈建议使用XML :: LibXML。
此模块的主要问题是大量选项以及这些选项交互的任意方式 - 通常会产生意外结果。
所以我们要使用XML::LibXML
模块,它与GNOME项目中的外部libxml2
库接口。这样做的好处是我们可以使用XPath表达式来查询我们的数据。要读取或写入CSV,应使用Text::CSV
模块。
use strict; use warnings;
use XML::LibXML;
use Text::CSV;
# load the data
my $data = XML::LibXML->load_xml(IO => \*STDIN) or die "Can't parse the XML";
# prepare CSV output:
my $csv = Text::CSV->new({ binary => 1, escape_char => "\\", eol => "\n" });
# Text::CSV doesn't like bareword filehandles
open my $output, '>&:utf8', STDOUT or die "Can't dup STDOUT: $!";
my @cols = qw/ name left width /; # the column names in the CSV
my @attrs = qw/ Name Left Width /; # the corresponding attr names in the XML
# print the header
$csv->print($output, \@cols);
# extract data
for my $label ($data->findnodes('//Label')) {
my @fields = map { $label->getAttribute($_) } @attrs;
$csv->print($output, \@fields);
}
测试数据(我冒昧地关闭宽度attr的值):
<foo>
<Label Name="lblIncidentTypeContent" Increasable="true" Left="140" Top="60"
Width="146" SpeechField="IncidentType_V" TextAlign="MiddleLeft" WidthPixel="-180"
WidthPercent="50" />
<Label Name="Another TypeContent" Increasable="true"
Width="123" SpeechField="IncidentType_V"
Left="41,42" Top="13"
TextAlign="TopLeft" WidthPixel="-180"
WidthPercent="50"
/>
</foo>
输出:
name,left,width
lblIncidentTypeContent,140,146
"Another TypeContent","41,42",123
答案 1 :(得分:1)
嗯,这是Perl你有几种方法可以做到: