【问题标题】:XML::Twig modify text of multiple elementsXML::Twig 修改多个元素的文本
【发布时间】:2018-11-07 12:08:57
【问题描述】:

我正在尝试更改源 XML 文件中三个元素的文本。

两个目标具有相同的元素名称 (ifw6:value),但存在于不同的标题下。第三个的元素名称与前两个不同。

程序成功执行,但打印原始 XML 文件而不做任何修改。调试语句让我相信它没有执行映射在twig_handlers 中的子例程。

#!/usr/bin/perl

use strict;
use warnings;

use XML::Twig;

my $text1 = "123456789";
my $text2 = "1234567";
my $text3 = "001";

my $twig = XML::Twig->new(
     pretty_print => 'indented',
     twig_handlers => {

         text => sub {

             my $targ1_2 = $_->next_elt('ifw6:value');
             my $targ3   = $_->next_elt('ifw4:relationship');

             if ($targ1_2->text eq 'target1') {
                 $targ1_2->set_text($text1);
             }

             if ($targ1_2->text eq 'target2') {
                 $targ1_2->set_text($text2);
             }

             if ($targ3->text eq 'target3') {
                 $targ3->set_text($text3);
             }

             $targ1_2->flush;
             $targ3->flush;
         }
    }
);


$twig->parsefile('text.xml');
$twig->print();

文本.xml

<SOAP-ENV>
   <SOAP-ENV:Header/>
   <SOAP-ENV:Body>
      <ifw:Information>
         <requestHeader>
            <ifw1:id/>
         </requestHeader>
         <ifw4:Miscellaneous>
            <ifw6:MiscVals xsi:type="type1">
               <ifw6:value>target1</ifw6:value>
            </ifw6:MiscVals>
            <ifw6:MiscVals xsi:type="type2">
              <ifw6:Vals xsi:type="type3">
                  <ifw6:value>target2</ifw6:value>
              </ifw6:Vals>
           </ifw6:MiscVals>
              <ifw4:relationship>target3</ifw4:relationship>
           </ifw4:Miscellaneous>
        </ifw:Information>
      </SOAP-ENV:Body>
</SOAP-ENV>

想要的结果

<SOAP-ENV>
   <SOAP-ENV:Header/>
   <SOAP-ENV:Body>
      <ifw:Information>
         <requestHeader>
            <ifw1:id/>
         </requestHeader>
         <ifw4:Miscellaneous>
            <ifw6:MiscVals xsi:type="type1">
               <ifw6:value>123456789</ifw6:value>
            </ifw6:MiscVals>
            <ifw6:MiscVals xsi:type="type2">
              <ifw6:Vals xsi:type="type3">
                  <ifw6:value>1234567</ifw6:value>
              </ifw6:Vals>
           </ifw6:MiscVals>
              <ifw4:relationship>001</ifw4:relationship>
           </ifw4:Miscellaneous>
        </ifw:Information>
      </SOAP-ENV:Body>
</SOAP-ENV>

【问题讨论】:

  • 您的 text 正在寻找像 &lt;text&gt; 这样的元素,而不是文本节点。在 XPath 中,您将使用 text(),但我不确定它是否适用于 XML::Twig
  • 搜索 ifw6:valueifw4:relationship 并修改其文本内容。
  • 正确的方法确实是在命名元素上使用twig_handlers,正如@Borodin 所说。要触发文本处理程序,您需要使用“#TEXT”,如果您习惯于 CSS 选择器,这无疑会令人困惑,但这种语法实际上早于 CSS :--(
  • @mirod:感谢您的确认。当然我应该记得#TEXT,但是代码要检查$_-&gt;parent-&gt;tag,比较麻烦。虽然,考虑到这一点,我怀疑文本节点是否是 XML::Twig::Elt 对象,而且我无法进行实验。
  • @Borodin 一个文本节点一个 XML::Twig::Elt 对象。为了使混合内容起作用,它必须这样做。它的标签“名称”是#PCDATA(或#CDATA),尽管您不能在#PCDATA(IIRC)上拥有处理程序

标签: xml perl text-parsing


【解决方案1】:

我认为这应该可以,但我目前没有办法测试它

my $twig = XML::Twig->new(

     pretty_print => 'indented',

     twig_handlers => {

         'ifw6:value' => sub {

             my $text = $_->trimmed_text;

             if ($text eq 'target1') {
                 $_->set_text($text1);
             }
             elsif ($text eq 'target2') {
                 $_->set_text($text2);
             }

             $_->flush;
         },

         'ifw4:relationship' => sub {

             my $text = $_->trimmed_text;

             if ($text eq 'target3') {
                 $_->set_text($text3);
             }

             $_->flush;
         }
    }

);

【讨论】:

    【解决方案2】:
    use strict;
    use warnings;
    use XML::Twig;
    
    my $text1 = "123456789";
    my $text2 = "12345678901011121314151";
    my $text3 = "001";
    
    my $twig = XML::Twig->new(
        pretty_print => 'indented',
        twig_handlers => {
            'ifw6:value[string()="target1"]' => sub {
                $_->set_text($text1);
            },
            'ifw6:value[string()="target2"]' => sub {
                $_->set_text($text2);
            },
            'ifw4:relationship[string()="target3"]' => sub {
                $_->set_text($text3);
            }
        }
    );
    
    $twig->parsefile('text.xml');
    $twig->print();
    

    使用刷新对我来说很奇怪,我不确定它是否完全需要。我认为你想要的结果 target2 替换缺少一些字符串。

    【讨论】:

      猜你喜欢
      • 2019-09-11
      • 1970-01-01
      • 2021-05-17
      • 2021-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-15
      • 2010-11-01
      相关资源
      最近更新 更多