将XML文件解析为字段
我需要从XML文件中读取行并将它们解析为字段。行定义为以“<”开头,以“/>”结尾的文本。它可以是由CR/LF分隔的单线或多线。下面是一条典型的线路:将XML文件解析为字段,xml,perl,parsing,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" /&g
<Label Name="lblIncidentTypeContent" Increasable="true" Left="140" Top="60"
Width="146 SpeechField="IncidentType_V" TextAlign="MiddleLeft" WidthPixel="-180"
WidthPercent="50" />
好吧,这是Perl,您有几种方法可以做到这一点:
- 蛮力。将文件插入,并在遇到开口时进行跟踪。完成后,开始收集名称/值对。当您看到右大括号时,请停止。这并不像听起来那么容易,因为您必须处理可能嵌套的XML元素
- 轻微的力量。使用基本库(如XML::Simple)加载文件,然后使用Data::Dumper以您选择的格式输出。前者给你一个散列,然后你可以玩你喜欢的键和值
- 使用XML库。CPAN中有很多,从非常接近底层libxml语义的到非常抽象的李>
好吧,这就是Perl,您有几种方法可以做到这一点:
- 蛮力。将文件插入,并在遇到开口时进行跟踪。完成后,开始收集名称/值对。当您看到右大括号时,请停止。这并不像听起来那么容易,因为您必须处理可能嵌套的XML元素
- 轻微的力量。使用基本库(如XML::Simple)加载文件,然后使用Data::Dumper以您选择的格式输出。前者给你一个散列,然后你可以玩你喜欢的键和值
- 使用XML库。CPAN中有很多,从非常接近底层libxml语义的到非常抽象的李>
不要将XML视为基于行的数据,因为它不是。相反,使用一个好的XML解析器,Perl有很多
不要使用XML::Simple!
它说它被弃用了:
不鼓励在新代码中使用此模块。还提供了其他模块,它们提供了更直观和一致的接口。特别推荐使用XML::LibXML
该模块的主要问题是选项数量庞大,以及这些选项之间的交互方式随意,通常会产生意想不到的结果
所以我们将使用模块,它与GNOME项目中的外部libxml2
库接口。这样做的好处是我们可以使用XPath表达式来查询数据。对于读取或写入CSV,应使用模块
使用严格;使用警告;
使用XML::LibXML;
使用Text::CSV;
#加载数据
我的$data=XML::LibXML->load\uxml(IO=>\*STDIN)或死“无法解析XML”;
#准备CSV输出:
我的$csv=Text::csv->new({binary=>1,escape\u char=>“\\”,eol=>“\n”});
#CSV不喜欢裸字文件句柄
打开我的$output,'>&:utf8',STDOUT或die“无法复制STDOUT:$!”;
my@cols=qw/名称左宽度/;#CSV中的列名
my@attrs=qw/名称左宽度/;#XML中相应的attr名称
#打印标题
$csv->print($output,\@cols);
#提取数据
对于我的$label($data->findnodes('//label')){
my@fields=map{$label->getAttribute($)}@attrs;
$csv->打印($output,\@字段);
}
测试数据(我随意关闭了宽度属性的值):
输出:
名称,左侧,宽度
lblIncidentTypeContent,140146
“另一种类型内容”,“41,42”,123
不要将XML视为基于行的数据,因为它不是。相反,使用一个好的XML解析器,Perl有很多
不要使用XML::Simple!
它说它被弃用了:
不鼓励在新代码中使用此模块。还提供了其他模块,它们提供了更直观和一致的接口。特别推荐使用XML::LibXML
该模块的主要问题是选项数量庞大,以及这些选项之间的交互方式随意,通常会产生意想不到的结果
所以我们将使用模块,它与GNOME项目中的外部libxml2
库接口。这样做的好处是我们可以使用XPath表达式来查询数据。对于读取或写入CSV,应使用模块
使用严格;使用警告;
使用XML::LibXML;
使用Text::CSV;
#加载数据
我的$data=XML::LibXML->load\uxml(IO=>\*STDIN)或死“无法解析XML”;
#准备CSV输出:
我的$csv=Text::csv->new({binary=>1,escape\u char=>“\\”,eol=>“\n”});
#CSV不喜欢裸字文件句柄
打开我的$output,'>&:utf8',STDOUT或die“无法复制STDOUT:$!”;
my@cols=qw/名称左宽度/;#CSV中的列名
my@attrs=qw/名称左宽度/;#XML中相应的attr名称
#打印标题
$csv->print($output,\@cols);
#提取数据
对于我的$label($data->findnodes('//label')){
my@fields=map{$label->getAttribute($)}@attrs;
$csv->打印($output,\@字段);
}
测试数据(我随意关闭了宽度属性的值):
输出:
名称,左侧,宽度
lblIncidentTypeContent,140146
“另一种类型内容”,“41,42”,123
如果您使用的是perl,请用它标记您的问题。我建议使用您所用语言的完整xml解析器库,而不是手动解析。如果您使用的是perl,请用它标记您的问题。我建议使用您所用语言的完整xml解析器库,而不是手工解析,这看起来就是我要找的。但是有一个问题,这段代码是否假设每个记录的属性总是以相同的顺序排列?如果是这样,那对我的数据不起作用。@EdWall不,代码不采用任何顺序:它使用@attrs
中的顺序。map{BLOCK}@items
只是一个奇特的foreach(@items){BLOCK}
循环。XML属性基本上是无序的