将XML文件解析为字段

时间:2013-10-23 19:55:28

标签: xml perl parsing

我需要从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(或任何其他类型的)编程以来已经很长时间了。欢迎任何帮助。

2 个答案:

答案 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你有几种方法可以做到:

  • 蛮力。将文件拖入,并在遇到开头时跟踪&lt;支撑。执行此操作时,请开始收集名称/值对。当你看到一个右大括号时,停下来。并不像听起来那么容易,因为你必须处理可能嵌套的XML元素。
  • 轻微的力量。使用XML :: Simple等基本库加载文件,然后使用Data :: Dumper以您选择的格式将其吐出。前者为您提供哈希,然后您可以使用所有类似的键和值。
  • 使用XML库。 CPAN中有很多,包括非常接近底层libxml语义和非常抽象的语义。