我正在尝试使用 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,
看起来代码没有进入自定义属性循环,我不知道为什么。
最佳答案
你的问题是“订单日期”——由于 ForceArray——也被强制成为一个 arrayref,正如你从已经存在的 Dumper 输出中看到的那样:
...
'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 ( @{ $data->{'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 或其他一些 pretty-print
如果您需要将其作为 GUI 显示给人类,请开发一个良好的 GUI 以匹配您的数据结构。
关于xml - 打印 XML 数组值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12169029/
我有多个ActiveRecord子类Item的实例数组,我需要根据最早的事件循环打印。在这种情况下,我需要打印付款和维护日期,如下所示:ItemAmaintenancerequiredin5daysItemBpaymentrequiredin6daysItemApaymentrequiredin7daysItemBmaintenancerequiredin8days我目前有两个查询,用于查找maintenance和payment项目(非排他性查询),并输出如下内容:paymentrequiredin...maintenancerequiredin...有什么方法可以改善上述(丑陋的)代
我的代码目前看起来像这样numbers=[1,2,3,4,5]defpop_threepop=[]3.times{pop有没有办法在一行中完成pop_three方法中的内容?我基本上想做类似numbers.slice(0,3)的事情,但要删除切片中的数组项。嗯...嗯,我想我刚刚意识到我可以试试slice! 最佳答案 是numbers.pop(3)或者numbers.shift(3)如果你想要另一边。 关于ruby-多次弹出/移动ruby数组,我们在StackOverflow上找到一
我需要读入一个包含数字列表的文件。此代码读取文件并将其放入二维数组中。现在我需要获取数组中所有数字的平均值,但我需要将数组的内容更改为int。有什么想法可以将to_i方法放在哪里吗?ClassTerraindefinitializefile_name@input=IO.readlines(file_name)#readinfile@size=@input[0].to_i@land=[@size]x=1whilex 最佳答案 只需将数组映射为整数:@land边注如果你想得到一条线的平均值,你可以这样做:values=@input[x]
我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为
我正在使用puppet为ruby程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这
这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife
我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R
我有一个这样的哈希数组:[{:foo=>2,:date=>Sat,01Sep2014},{:foo2=>2,:date=>Sat,02Sep2014},{:foo3=>3,:date=>Sat,01Sep2014},{:foo4=>4,:date=>Sat,03Sep2014},{:foo5=>5,:date=>Sat,02Sep2014}]如果:date相同,我想合并哈希值。我对上面数组的期望是:[{:foo=>2,:foo3=>3,:date=>Sat,01Sep2014},{:foo2=>2,:foo5=>5:date=>Sat,02Sep2014},{:foo4=>4,:dat
我正在尝试在Ruby中制作一个cli应用程序,它接受一个给定的数组,然后将其显示为一个列表,我可以使用箭头键浏览它。我觉得我已经在Ruby中看到一个库已经这样做了,但我记不起它的名字了。我正在尝试对soundcloud2000中的代码进行逆向工程做类似的事情,但他的代码与SoundcloudAPI的使用紧密耦合。我知道cursesgem,我正在考虑更抽象的东西。广告有没有人见过可以做到这一点的库或一些概念证明的Ruby代码可以做到这一点? 最佳答案 我不知道这是否是您正在寻找的,但也许您可以使用我的想法。由于我没有关于您要完成的工作
我使用Ember作为我的前端和GrapeAPI来为我的API提供服务。前端发送类似:{"service"=>{"name"=>"Name","duration"=>"30","user"=>nil,"organization"=>"org","category"=>nil,"description"=>"description","disabled"=>true,"color"=>nil,"availabilities"=>[{"day"=>"Saturday","enabled"=>false,"timeSlots"=>[{"startAt"=>"09:00AM","endAt"=>