【问题标题】:Copy XML value using XML::Twig使用 XML::Twig 复制 XML 值
【发布时间】:2013-01-01 06:26:29
【问题描述】:

我有嵌套的 XML 标记,并且需要使用 XML::TwigProduct XML 中的 ExternalId 值设置为 ProductPageURL 标记。

<Products>
    <Product>
      <ExternalId>317851</ExternalId>
      <ProductPageUrl></ProductPageUrl>
    </Product>
    <Product>
      <ExternalId>316232</ExternalId>
      <ProductPageUrl></ProductPageUrl>
    </Product>
    <Product>
      <ExternalId>13472</ExternalId>
      <ProductPageUrl></ProductPageUrl>
    </Product>
</Products>

预期结果:

<Products>
    <Product>
      <ExternalId>PF317851</ExternalId>
      <ProductPageUrl>317851</ProductPageUrl>
    </Product>
    <Product>
      <ExternalId>PF316232</ExternalId>
      <ProductPageUrl>316232</ProductPageUrl>
    </Product>
    <Product>
      <ExternalId>PF13472</ExternalId>
      <ProductPageUrl>13472</ProductPageUrl>
    </Product>
    </Products>

我使用XML::Twig 使用以下逻辑:

my $twig = XML::Twig->new( 
        twig_handlers => {      
            'Product/ExternalId' => sub {
                $_->prefix( 'PF' );
            },
             'Product/ProductPageUrl' => sub {
                $_->set_text($_->get('Product/ExternalId'));
            }, 
                
        },
        pretty_print => 'indented',
    keep_encoding => 1,
    )->parsefile($xml_path_filename )->print_to_file($xml_path_filename);

您能告诉我如何简化代码吗?我无法达到预期的效果。

【问题讨论】:

    标签: perl xml-parsing xml-twig


    【解决方案1】:

    您的初始代码中有两个问题:首先我不认为get 是一个 XML::Twig::Elt 方法。然后您首先为ExternalId 文本添加前缀,然后(一旦添加前缀)尝试使用它来更新ProductPageUrl。那是行不通的。在这种情况下,我认为您最好使用单个处理程序,用于 Product 标记,您可以在其中获取 id 数据,然后更新两个子元素。

    这是一个解决方案,编写为测试,因此如果您的输出发生变化,更新更容易:

    #!/usr/bin/perl
    
    use strict;
    use warnings;
    
    use Test::More tests => 1;
    
    use XML::Twig;
    
    # in and expected are in the DATA section, separated by 2 \n
    my( $in, $expected)= do { local $/="\n\n"; <DATA>};
    
    my $t= XML::Twig->new( twig_handlers => { Product => \&update_product },
                           keep_spaces => 1,
                         )     
                     ->parse( $in);
    
    is( $t->sprint, $expected, "one test to rule them all");
    
    sub update_product
      { my( $t, $product)= @_;
        my $id= $product->field( 'ExternalId');
        $product->first_child( 'ExternalId')->prefix( 'PF');
        $product->first_child( 'ProductPageUrl')->set_text( $id);
      }
    
    __DATA__
    <Products>
        <Product>
          <ExternalId>317851</ExternalId>
          <ProductPageUrl></ProductPageUrl>
        </Product>
        <Product>
          <ExternalId>316232</ExternalId>
          <ProductPageUrl></ProductPageUrl>
        </Product>
        <Product>
          <ExternalId>13472</ExternalId>
          <ProductPageUrl></ProductPageUrl>
        </Product>
    </Products>
    
    <Products>
        <Product>
          <ExternalId>PF317851</ExternalId>
          <ProductPageUrl>317851</ProductPageUrl>
        </Product>
        <Product>
          <ExternalId>PF316232</ExternalId>
          <ProductPageUrl>316232</ProductPageUrl>
        </Product>
        <Product>
          <ExternalId>PF13472</ExternalId>
          <ProductPageUrl>13472</ProductPageUrl>
        </Product>
    </Products>
    

    【讨论】:

      【解决方案2】:

      这是一种方法:

      use warnings;
      use strict;
      use XML::Twig;
      
      my $twig = XML::Twig->new( 
          twig_handlers => {      
              Product => \&prod,
          },
          pretty_print => 'indented',
          keep_encoding => 1,
      );
      
      $twig->parse(q(
      <Products>
          <Product>
            <ExternalId>317851</ExternalId>
            <ProductPageUrl></ProductPageUrl>
          </Product>
          <Product>
            <ExternalId>316232</ExternalId>
            <ProductPageUrl></ProductPageUrl>
          </Product>
          <Product>
            <ExternalId>13472</ExternalId>
            <ProductPageUrl></ProductPageUrl>
          </Product>
      </Products>
      ));
      
      $twig->print();
      
      sub prod {
          my ($t, $prod) = @_;
          my $extid = $prod->first_child('ExternalId');
          my $id = $extid->text();
          $extid->prefix('PF');
          my $url = $prod->first_child('ProductPageUrl');
          $url->set_text($id);
      }
      

      输出

      <Products>
        <Product>
          <ExternalId>PF317851</ExternalId>
          <ProductPageUrl>317851</ProductPageUrl>
        </Product>
        <Product>
          <ExternalId>PF316232</ExternalId>
          <ProductPageUrl>316232</ProductPageUrl>
        </Product>
        <Product>
          <ExternalId>PF13472</ExternalId>
          <ProductPageUrl>13472</ProductPageUrl>
        </Product>
      </Products>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-08-03
        • 1970-01-01
        • 2011-11-19
        • 2019-08-14
        • 2018-08-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多