0

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

4

2 回答 2

3

不要将 XML 视为基于行的数据,因为它不是。相反,使用一个好的 XML 解析器,Perl 有很多。

不要使用 XML::Simple!

自己的文档说它已被弃用:

不鼓励在新代码中使用此模块。其他模块也可以提供更直接和一致的接口。特别是,强烈推荐使用 XML::LibXML。

这个模块的主要问题是大量的选项以及这些选项交互的任意方式——通常会产生意想不到的结果。

所以我们将使用XML::LibXML模块,它与libxml2GNOME 项目的外部库接口。这样做的好处是我们可以使用 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);
}

测试数据(我冒昧地关闭了Width 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
于 2013-10-24T09:31:19.623 回答
1

好吧,这是 Perl,你有几种方法可以做到:

  • 蛮力。将文件插入,并跟踪您何时遇到开头的 < 大括号。当你这样做时,开始收集名称/值对。当你看到一个右括号时,停下来。不像听起来那么容易,因为您必须处理可能嵌套的 XML 元素。
  • 轻微的力量。使用 XML::Simple 等基本库加载文件,然后使用 Data::Dumper 以您选择的格式将其输出。前者给你一个哈希,然后你可以随意使用键和值。
  • 使用 XML 库。CPAN 中有很多,从非常接近底层 libxml 语义的到非常抽象的。
于 2013-10-23T21:19:25.030 回答