XML 到 CSV,在 Perl 中包含嵌套和明确的元素
XML to CSV with nested and definite elements in Perl
我需要将 xml 文件转换为 csv 格式。但是我在 csv 文件中不需要 XML 的所有信息,只需要 2 个元素(IP 地址和设备 ID)。
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use XML::Simple;
#Elements, that I want see in my csv
my @Fields = qw{id, ipAddress};
open(my $out, '>', 'output.csv') or die "Output: $!\n";
print $out join(',', @Fields) . "\n";
my $xml = XMLin('input.xml', ForceArray => ['entity']);
foreach my $entity (@{$xml->{entity}}) {
no warnings;
print $out join(',', map{$_->{content}} @{$entity}{@Fields}) . "\n";
Input.xml
<?xml version="1.0" ?>
<queryResponse last="41" first="0" count="42" type="Devices" responseType="listEntityInstances" requestUrl="https://hostname/webacs/api/v1/data/Devices?.full=true" rootUrl="https://hostname/webacs/api/v1/data">
<entity dtoType="devicesDTO" type="Devices" url="https://hostname/webacs/api/v1/data/Devices/20">
<devicesDTO displayName="20" id="20">
<clearedAlarms>1</clearedAlarms>
<collectionDetail><status><general code="SUCCESS"/></status></collectionDetail>
<collectionTime>2017-03-30T09:47:07.606+02:00</collectionTime>
<creationTime>2016-02-29T17:32:13.116+01:00</creationTime>
<ipAddress>1.1.1.1</ipAddress>
<location> </location>
<majorAlarms>0</majorAlarms>
<softwareType>IOS</softwareType>
<softwareVersion>12.2(55)SE9</softwareVersion>
<warningAlarms>0</warningAlarms>
</devicesDTO>
</entity>
<entity dtoType="devicesDTO" type="Devices" url="https://hostname/webacs/api/v1/data/Devices/21">
<devicesDTO displayName="21" id="21">
<clearedAlarms>1</clearedAlarms>
<collectionDetail><status><general code="SUCCESS"/></status></collectionDetail>
<collectionTime>2017-03-30T09:47:07.606+02:00</collectionTime>
<creationTime>2016-02-29T17:32:13.116+01:00</creationTime>
<ipAddress>2.2.2.2</ipAddress>
<location> </location>
<majorAlarms>0</majorAlarms>
<softwareType>IOS</softwareType>
<softwareVersion>12.2(55)SE9</softwareVersion>
<warningAlarms>0</warningAlarms>
</devicesDTO>
</entity>
</queryResponse>
结果我有
id, ipAddress
,
,
我不确定:
my $xml = XMLin('input.xml', ForceArray => ['entity']);
foreach my $entity (@{$xml->{entity}})
对我来说是正确的。我应该用标签 entity 来做吗?
在处理XML::Simple时,先用Data::Dumper看数据结构总是好的。
foreach my $entity ( @{ $xml->{entity} } ) {
print Dumper $entity;
这会告诉你:
$VAR1 = {
'url' => 'https://hostname/webacs/api/v1/data/Devices/20',
'type' => 'Devices',
'dtoType' => 'devicesDTO',
'devicesDTO' => {
'displayName' => '20',
'creationTime' => '2016-02-29T17:32:13.116+01:00',
'warningAlarms' => '0',
'ipAddress' => '1.1.1.1',
'clearedAlarms' => '1',
'majorAlarms' => '0',
'collectionDetail' => '<status><general code="SUCCESS"/></status>',
'location' => {},
'collectionTime' => '2017-03-30T09:47:07.606+02:00',
'softwareType' => 'IOS',
'id' => '20',
'softwareVersion' => '12.2(55)SE9'
}
};
很明显,您的 @Fields
放错了地方。这些键不直接在 $entity
中,而是在 $entity->{devicesDTO}
.
中
也没有必要将 $_->{content}
与 map
一起使用。实际上,该数据结构中没有 content
个键。
foreach my $entity ( @{ $xml->{entity} } ) {
print join( ',', @{ $entity->{devicesDTO} }{@Fields} ) . "\n";
}
这将产生输出
id,ipAddress
20,1.1.1.1
21,2.2.2.2
请注意,您的 qw{}
中有一个不需要的逗号。 qw
的想法是您不需要使用逗号。您还应该决定是否希望变量具有小写字母。混合是不好的风格,Perl 中的约定是使用 snake case。
my @fields = qw{id ipAddress};
我需要将 xml 文件转换为 csv 格式。但是我在 csv 文件中不需要 XML 的所有信息,只需要 2 个元素(IP 地址和设备 ID)。
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use XML::Simple;
#Elements, that I want see in my csv
my @Fields = qw{id, ipAddress};
open(my $out, '>', 'output.csv') or die "Output: $!\n";
print $out join(',', @Fields) . "\n";
my $xml = XMLin('input.xml', ForceArray => ['entity']);
foreach my $entity (@{$xml->{entity}}) {
no warnings;
print $out join(',', map{$_->{content}} @{$entity}{@Fields}) . "\n";
Input.xml
<?xml version="1.0" ?>
<queryResponse last="41" first="0" count="42" type="Devices" responseType="listEntityInstances" requestUrl="https://hostname/webacs/api/v1/data/Devices?.full=true" rootUrl="https://hostname/webacs/api/v1/data">
<entity dtoType="devicesDTO" type="Devices" url="https://hostname/webacs/api/v1/data/Devices/20">
<devicesDTO displayName="20" id="20">
<clearedAlarms>1</clearedAlarms>
<collectionDetail><status><general code="SUCCESS"/></status></collectionDetail>
<collectionTime>2017-03-30T09:47:07.606+02:00</collectionTime>
<creationTime>2016-02-29T17:32:13.116+01:00</creationTime>
<ipAddress>1.1.1.1</ipAddress>
<location> </location>
<majorAlarms>0</majorAlarms>
<softwareType>IOS</softwareType>
<softwareVersion>12.2(55)SE9</softwareVersion>
<warningAlarms>0</warningAlarms>
</devicesDTO>
</entity>
<entity dtoType="devicesDTO" type="Devices" url="https://hostname/webacs/api/v1/data/Devices/21">
<devicesDTO displayName="21" id="21">
<clearedAlarms>1</clearedAlarms>
<collectionDetail><status><general code="SUCCESS"/></status></collectionDetail>
<collectionTime>2017-03-30T09:47:07.606+02:00</collectionTime>
<creationTime>2016-02-29T17:32:13.116+01:00</creationTime>
<ipAddress>2.2.2.2</ipAddress>
<location> </location>
<majorAlarms>0</majorAlarms>
<softwareType>IOS</softwareType>
<softwareVersion>12.2(55)SE9</softwareVersion>
<warningAlarms>0</warningAlarms>
</devicesDTO>
</entity>
</queryResponse>
结果我有
id, ipAddress
,
,
我不确定:
my $xml = XMLin('input.xml', ForceArray => ['entity']);
foreach my $entity (@{$xml->{entity}})
对我来说是正确的。我应该用标签 entity 来做吗?
在处理XML::Simple时,先用Data::Dumper看数据结构总是好的。
foreach my $entity ( @{ $xml->{entity} } ) {
print Dumper $entity;
这会告诉你:
$VAR1 = {
'url' => 'https://hostname/webacs/api/v1/data/Devices/20',
'type' => 'Devices',
'dtoType' => 'devicesDTO',
'devicesDTO' => {
'displayName' => '20',
'creationTime' => '2016-02-29T17:32:13.116+01:00',
'warningAlarms' => '0',
'ipAddress' => '1.1.1.1',
'clearedAlarms' => '1',
'majorAlarms' => '0',
'collectionDetail' => '<status><general code="SUCCESS"/></status>',
'location' => {},
'collectionTime' => '2017-03-30T09:47:07.606+02:00',
'softwareType' => 'IOS',
'id' => '20',
'softwareVersion' => '12.2(55)SE9'
}
};
很明显,您的 @Fields
放错了地方。这些键不直接在 $entity
中,而是在 $entity->{devicesDTO}
.
也没有必要将 $_->{content}
与 map
一起使用。实际上,该数据结构中没有 content
个键。
foreach my $entity ( @{ $xml->{entity} } ) {
print join( ',', @{ $entity->{devicesDTO} }{@Fields} ) . "\n";
}
这将产生输出
id,ipAddress
20,1.1.1.1
21,2.2.2.2
请注意,您的 qw{}
中有一个不需要的逗号。 qw
的想法是您不需要使用逗号。您还应该决定是否希望变量具有小写字母。混合是不好的风格,Perl 中的约定是使用 snake case。
my @fields = qw{id ipAddress};