2012-08-28 62 views
3

我想使用perl和XML :: Simple将XML文件中的少量数据提取到csv文件中。打印XML数组值

下面是数据的编辑版本:使用该脚本

<?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(...),但不适用于只有一个数据元素的文件,并且a很明显,这段代码从来没有进入定制属性数组来打印任何东西。

我在做什么错?

更新:

改变在上述的循环代码这样:

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,

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

+0

要添加到你的其他出色的问题,你能否也请粘贴'print Dumper($ data);'的输出?这会让答案变得更加简单 - 坦率地说,可能会让你知道问题的原因:) +1 – DVK

回答

3

您的问题是“订单日期” - 由于ForceArray - 也越来越强制为数组引用,作为你一个从已经存在的自卸车输出看到:

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

因此,你需要做两件事情之一:

  • 如果订单日期将始终是一个单一的值,硬编码印刷第一阵列值:

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

    XML::Simple POD显示除了一个简单的ForceArray=>1选项外,您还可以在can also pass列表中选择要强制插入数组的限定标签(例如,ForceArray => [ "custom-attributes", "custom-attribute" ]

    • 如果order-date可以有多个标签,简单地打印在一个循环中,你已经在下面等多个标签做:

      的foreach我的$ order_date的(@ {$数据 - > {'订单-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或者如果你需要将其转换以示人,用Data::Dumper或部分转换成JSON

  • 其他漂亮的打印机

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

+0

非常感谢。我已经用结果更新了上面的问题。它仍然没有进入自定义属性循环。是我的打印'在1级'的东西造成问题(我试图消除他们,但仍然没有得到任何东西)。 –

+0

FWIW,此代码用于创建现有数据仓库的馈送。实际上,我将使用的XML包含比上面显示的数据元素更多的数据元素,其中没有一个会前往EDW。 –

2

除了从DVK答案:

我相信你需要附上最外层循环

的foreach $ O(@ {$数据 - > {为了}})

在另一个循环,为“订单”的项目似乎被封闭到“订单”项目

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

最好的问候,

Olivier。