【问题标题】:XML SIMPLE PERL - Looping through child nodes problemXML SIMPLE PERL - 循环通过子节点问题
【发布时间】:2018-10-26 17:43:48
【问题描述】:

我有一些 perl 代码

my $res = $ua->get( $access->to_url );
if ($res->is_success) {
my $ref = XMLin( $res->content );


    my $xml = new XML::Simple;
    $data = $xml->XMLin($res->content,ForceArray => 1);
    #print $res->content;
    for my $purchase ( @{ $data->{PurchaseOrders}->{PurchaseOrder}} )

这点没问题....

当我尝试循环遍历子元素时,如果只有一个子元素

我收到“不是数组引用”错误

for my $item ( @{$purchase->{LineItems}->{LineItem}} ) 
    {
    $itemCode = $item->{ItemCode}; 
    }

XML 结构是这样的

PurchaseOrders

    PurchaseOrder

        LineItems

            LineItem

我知道 xml simple 的一个问题,我必须强制数组,但我不确定如何在子节点上强制数组

我在 stackoverflow 上发现这篇文章似乎非常接近我的确切问题,但我正在努力解决如何在我的代码中执行它

perl, parsing XML using XML::Simple

   $VAR1 = {
      'PurchaseOrderID' => '82fa50d6-fd45-4fd2-b42d-035aaaa39a2c',
      'LineAmountTypes' => 'Exclusive',
      'SentToContact' => 'true',
      'AttentionTo' => 'sxxxx',
      'Status' => 'AUTHORISED',
      'LineItems' => {
                       'LineItem' => {
                                       'LineAmount' => '57.61',
                                       'Quantity' => '1.0000',
                                       'UnitAmount' => '57.6100',
                                       'LineItemID' => 'e295d55d-68bd',
                                       'Description' => 'xxx',
                                       'ItemCode' => 'xxx',
                                       'TaxAmount' => '11.52',
                                       'AccountCode' => '310',
                                       'TaxType' => 'INPUT2'
                                     }
                     },
      'UpdatedDateUTC' => '2018-10-26T14:19:19.053',
      'CurrencyCode' => 'GBP',
      'Contact' => {

包括我的打印转储器中的一个片段 - 请注意,它只是重要部分的片段,一切都很好,直到它到达订单项

这里还有 XML 文件

<PurchaseOrder>
  <PurchaseOrderID>82fa50</PurchaseOrderID>
  <PurchaseOrderNumber>PO-0029</PurchaseOrderNumber>
  <Date>2018-10-26T00:00:00</Date>
  <DeliveryDate>2018-10-28T00:00:00</DeliveryDate>
  <DeliveryAddress>Address/DeliveryAddress>
  <AttentionTo>XXX</AttentionTo>
  <SentToContact>true</SentToContact>
  <Reference>000000078</Reference>
  <CurrencyRate>1.000000</CurrencyRate>
  <CurrencyCode>GBP</CurrencyCode>
  <Contact>
    <ContactID>f203ed00-8cd1-4e4d-9b76-f5e7d90a3c19</ContactID>
    <ContactStatus>ACTIVE</ContactStatus>
    <Name>XXX</Name>
    <FirstName>XXXy</FirstName>
    <LastName>XXX</LastName>
    <Addresses>
      <Address>
        <AddressType>XXX</AddressType>
        <AddressLine1>XXX</AddressLine1>
        <AddressLine2>XXX</AddressLine2>
        <City>XXX</City>
        <Region>XXX</Region>
        <PostalCode>XXX</PostalCode>
        <Country>GBR</Country>
      </Address>
      <Address>
        <AddressType>XXX</AddressType>
        <AddressLine1>Unit 1-3</AddressLine1>
        <AddressLine2>XXX</AddressLine2>
        <City>XXX</City>
        <Region>West Yorkshire</Region>
        <PostalCode>POSTCODE</PostalCode>
        <Country>GBR</Country>
      </Address>
    </Addresses>
    <UpdatedDateUTC>2018-10-08T17:19:55.083</UpdatedDateUTC>
    <DefaultCurrency>GBP</DefaultCurrency>
  </Contact>
  <BrandingThemeID>2ffe566f-7a88-486a-938c-639d27966197</BrandingThemeID>
  <Status>AUTHORISED</Status>
  <LineAmountTypes>Exclusive</LineAmountTypes>
  <LineItems>
    <LineItem>
      <ItemCode>xxx</ItemCode>
      <Description>des</Description>
      <UnitAmount>57.6100</UnitAmount>
      <TaxType>INPUT2</TaxType>
      <TaxAmount>11.52</TaxAmount>
      <LineAmount>57.61</LineAmount>
      <AccountCode>310</AccountCode>
      <Quantity>1.0000</Quantity>
      <LineItemID>e295d55d-68bd-41b0-a0b1-cf1f2d5b7a4f</LineItemID>
    </LineItem>
  </LineItems>
  <SubTotal>57.61</SubTotal>
  <TotalTax>11.52</TotalTax>
  <Total>69.13</Total>
  <UpdatedDateUTC>2018-10-26T14:19:19.053</UpdatedDateUTC>
  <HasAttachments>false</HasAttachments>
</PurchaseOrder>

【问题讨论】:

  • 请向我们展示使用Data::Dumper时的输出。请使该输出简短但相关。您已经在使用ForceArray,这意味着您的所有结构都应该是数组,但数据中的某处似乎有问题。
  • 您使用的是哪个 Perl 版本?想知道您是否不小心使用了伪散列(一个旧的已删除的错误功能)并在您的散列取消引用之一之前丢失了所需的 -&gt;[0]
  • $purchase-&gt;{LineItems}-&gt;{LineItem} 对于某些项目可能未定义
  • 添加了我的打印转储器的片段,很抱歉应该原始发布此内容

标签: perl xml-simple


【解决方案1】:

您可以通过使用返回可理解 XML 树的对象的 XML 解析器来避免 ForceArray 问题和混淆数据结构。如果您了解 CSS,Mojo::DOM 是一个不错的选择。

use Mojo::DOM;

my $dom = Mojo::DOM->new->xml(1)->parse($res->decoded_content);
for my $purchase ($dom->find('PurchaseOrders > PurchaseOrder')->each) {
  # $purchase is a Mojo::DOM object representing a PurchaseOrder element
  for my $item ($purchase->find('LineItems > LineItem')->each) {
    # It's unclear if ItemCode is an an attribute or a sub-element; assuming sub-element
    my $itemCode = $item->at('ItemCode')->text;
    ...
  }
}

XML::LibXML 是另一个可以类似使用的选项,但使用 XPath 或 DOM 而不是 CSS 来定位元素。

use XML::LibXML qw( );

my $doc = XML::LibXML->load_xml(string => $res->decoded_content);
for my $purchase ($doc->findodes('/PurchaseOrders/PurchaseOrder')) {
  # $purchase is a XML::LibXML::Element object representing a PurchaseOrder element
  for my $item ($purchase->findnodes('LineItems/LineItem')) {
    # It's unclear if ItemCode is an an attribute or a sub-element; assuming sub-element
    my $itemCode = $item->findvalue('ItemCode');
    ...
  }
}

【讨论】:

  • 嗨,谢谢,遗憾的是,我用 XML SIMPLE 编写了这么多代码,这是我必须解决的唯一最后一个问题,并且真的想避免重写
  • @ikegami 我不确定上次编辑的目的,XML::LibXML 接受 XPath 查询而不是 CSS 查询,DOM 遍历在两个库中的工作方式相同。
  • Mojo::DOM,尽管它的名字,并不遵循 DOM 规范。另一方面,XML::LibXML 确实实现了(部分)DOM API。希望使用它而不是 CSS 选择器或 XPath 选择器的人可以使用 XML::LibXML
  • @ikegami 如果我理解你所指的正确,Mojo::DOM 提供了一个具有相同功能的遍历 API,只是没有遵循 XML::LibXML 关于对象类型的规范.因此,将其称为独特功能有点误导,仅此而已。
  • 提供已知的标准接口(例如 CSS、XPath 或 DOM)是一项功能。这就是为什么你费心提它的原因。我刚刚添加了缺少的那个。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多