打印XML数组值

时间:2012-08-28 23:37:54

标签: xml perl xml-parsing xml-simple

我正在尝试使用perl和XML :: Simple从XML文件中将少量数据提取到csv文件中。

以下是数据的编辑版本:

<?xml version="1.0" encoding="UTF-8"?>
<orders xmlns="http://www.demandware.com/xml/impex/order/2006-10-31">
    <order order-no="W100148941">
        <order-date>2011-08-22T16:15:47.000Z</order-date>
        <custom-attributes>
            <custom-attribute attribute-id="basket_notes">bnotes974211</custom-attribute>
            <custom-attribute attribute-id="omOrderID">974211</custom-attribute>
        </custom-attributes>
    </order>
</orders>

使用此脚本:

#!/usr/bin/perl

use XML::Simple;
use Data::Dumper;

$xml = new XML::Simple;
$data = $xml->XMLin("$ARGV[0]", ForceArray=>1);


print Dumper($data);
foreach $o (@{$data->{order}}) {
    print "$ARGV[1]", ",";
    print "$ARGV[2]", ",";
    print "$ARGV[3]", ",";
    print "$ARGV[4]", ",";
    print $o->{"order-no"}, ",";
    print $o->{"order-date"}, ",";
    foreach my $o ( @{ $data->{'custom-attribute'} } ) {
        print 'in level 1';
        foreach my $attr ( @{ $data->{'custom-attribute'} } ) {
            print 'in level 2';
            if ( $attr->{'attribute-id'} eq 'basket_notes' ) {
                print '"', $data->{'content'}, '"', ",";
            }
        }
    }
    print "\n";
}

告诉我这个输出:

,,,,W100148941,ARRAY(0x7f7f63a524c0),

不使用ForceArray选项XMLin将使用正确的值替换上面的ARRAY(...),但不能使用只有一个数据元素的文件,并且很明显,此代码从未进入自定义属性数组可以打印任何内容。

我做错了什么?

更新

将上面的循环代码更改为:

foreach $o (@{$data->{order}})
{
print "$ARGV[1]", ",";
print "$ARGV[2]", ",";
print "$ARGV[3]", ",";
print "$ARGV[4]", ",";
print $o->{"order-no"}, ",";
#print $o->{"order-date"}, ",";
print $o->{"order-date"}->[0], ",";
foreach my $o ( @{ $data->{'custom-attributes'} } ) {
    print 'in level 1';
   foreach my $attr ( @{ $o->{'custom-attribute'} } ) {
        print 'in level 2';
        if ( $attr->{'attribute-id'} eq 'omOrderID' ) {
            print '"', $data->{'content'}, '"', ",";
        }
    }
}

print "\n";
}

得出这个:

,,,, W100148941,2011-08-22T16:15:47.000Z,

看起来代码只是没有进入自定义属性循环,我不知道为什么。

2 个答案:

答案 0 :(得分:3)

你的问题是“订单日期” - 来自ForceArray - 也被迫成为一个arrayref,正如你已经存在的Dumper输出所示:

...
     'order-date' => [
                     '2011-08-22T16:15:47.000Z'
                     ],

因此,您需要做以下两件事之一:

  • 如果order-date始终为单个值,则硬编码打印第一个数组值:

    print $o->{"order-date"}->[0], ",";
    
  • 如果order-date始终为单个值,请通过传递更详细的ForceArray指令来更改构造函数参数。

    XML::Simple POD显示除了简单的ForceArray=>1选项外,您can also pass要强制插入数组的有限标记列表(例如ForceArray => [ "custom-attributes", "custom-attribute" ]

    • 如果order-date可以包含多个代码,只需将其打印在循环中,就像下面其他多个代码一样:

      预告我的$ order_date(@ {$ data-&gt; {'order-date'}}){      打印“$ order_date,”


此外,您的嵌套循环中有几个错误。

你的第一个循环应该是

foreach my $o ( @{ $data->{'custom-attributes'} } ) { # You had "attribute"

并且第二个循环应该遍历那个子结构:

    foreach my $attr ( @{ $o->{'custom-attribute'} } ) { # instead of $data->...

将所有这些放在一边,从我相当可观的经验来看,将XML转换为平面文件(CSV)是一个不好的主意,温和地说。请认真考虑一下你是否做得对。

没有狡猾的编码,无法正确或轻松地映射数据;并且稍后解码那个狡猾的编码并不比简单地再次读取XML更容易。

  • 如果您需要转换它以便其他程序可以读取,请保留XML或转换为JSON

  • 如果您需要将其转换为向人展示,请使用Data::Dumper或其他漂亮的打印机

  • 如果您需要将其作为GUI显示给人,请开发一个良好的GUI以匹配您的数据结构。

答案 1 :(得分:2)

除了DVK的回答:

我相信你需要把最外层的循环包围起来

foreach $ o(@ {$ data-&gt; {order}})

在另一个循环中,因为“订单”项似乎被包含在“订单”项

    foreach $oo (@{$data->{orders}}) {
       foreach $o (@{$oo->{order}})
       {
       ....
       }
    }  #additional closing for the additional foreach

致以最诚挚的问候,

奥利弗。