【问题标题】:XML Parsing and replacing in PerlPerl 中的 XML 解析和替换
【发布时间】:2012-04-30 02:52:39
【问题描述】:

觉得问这个很愚蠢,但到目前为止已经浪费了整个下午的时间,而且离解决方案还差得远。我正在自动推出一些 Jenkins 实例,并且我想复制现有的作业。

我在 perl 脚本中解析 config.xml 文件,需要替换某些字符串元素。

我几乎使用 XML::Simple 到达那里,但我发现它丢失了输出所需的数据结构。进一步阅读,我发现这就是 XML::Simple 的工作方式。所以我开始尝试 XML::LibXML

示例输入是:

<project>
  <properties>
    <hudson.model.ParametersDefinitionProperty>
      <parameterDefinitions>
        <hudson.model.ChoiceParameterDefinition>
          <name>environment</name>
          <choices class="java.util.Arrays$ArrayList">
            <a class="string-array">
              <string>1</string>
              <string>2</string>
              <string>3</string>
              <string>4</string>
              <string>5</string>
            </a>
          </choices>
        </hudson.model.ChoiceParameterDefinition>
      </parameterDefinitions>
    </hudson.model.ParametersDefinitionProperty>
    <de.pellepelster.jenkins.walldisplay.WallDisplayJobProperty/>
  </properties>
</project>

例如,我想要实现的是删除所有 &lt;string&gt;n&lt;/string&gt; 元素,然后添加一些不同的元素。

而且代码应该比较简单:

my $p           = XML::LibXML->new;
my $d           = $p->parse_string($input);
my $params  = $d->findnodes('/project/properties/hudson.model.ParametersDefinitionProperty/parameterDefinitions/hudson.model.ChoiceParameterDefinition/choices');

这将返回一个节点列表。但我似乎无法操纵此列表中的元素。如果我做一个

print $params->to_literal;

然后我可以看到我已经获得了我想要操作的数据。但我正在努力迈出下一步。谁能帮我指出正确的方向?

【问题讨论】:

  • 你应该看看XML::Twig。它提供了基于 DOM 的 XML 操作所需的一切。

标签: xml perl xml-parsing


【解决方案1】:

nodeList 你有一个XML::LibXML::Node 对象的列表。您要做的是遍历每个节点,调用父节点的 removeChild 函数传入子节点。

这是一个使用 XML::LibXML 的示例:

my $params  = $d->findnodes('/project/properties/hudson.model.ParametersDefinitionProperty/parameterDefinitions/hudson.model.ChoiceParameterDefinition/choices/a');
foreach my $node ($params->[0]->childNodes()) {

    $params->[0]->removeChild($node);
}

我假设元素的父节点将始终命名为“a”,并且“选择”节点下只有一个节点。然后,您可以使用print $d-&gt;toString(); 再次打印出 XML。

【讨论】:

    【解决方案2】:

    这是一个XML::Twig 程序,它将删除a 下的string 标签。

    use v5.10;
    
    my $xml = <<'HERE';
    <project>
      <properties>
        <hudson.model.ParametersDefinitionProperty>
          <parameterDefinitions>
            <hudson.model.ChoiceParameterDefinition>
              <name>environment</name>
              <choices class="java.util.Arrays$ArrayList">
                <a class="string-array">
                  <string>1</string>
                  <string>2</string>
                  <string>3</string>
                  <string>4</string>
                  <string>5</string>
                </a>
              </choices>
            </hudson.model.ChoiceParameterDefinition>
          </parameterDefinitions>
        </hudson.model.ParametersDefinitionProperty>
        <de.pellepelster.jenkins.walldisplay.WallDisplayJobProperty/>
      </properties>
    </project>
    HERE
    
    use XML::Twig;
    
    my $twig = XML::Twig->new(   
        twig_handlers => { 
            a   => sub {
                foreach my $child ( $_->children ) {
                    say "Found ", $child->text;
                    $child->cut;
                    }
                },
          },
        pretty_print => 'indented',
        );
    
    $twig->parse( $xml );
    $twig->flush; 
    

    如果你想改变标签名称和文本,设置是一样的,只是你稍微改变一下处理程序。

    my $twig = XML::Twig->new(   
        twig_handlers => { 
            a   => sub {
                foreach my $child ( $_->children ) {
                    $child->set_tag( 'new_name' );
                    $child->set_text( $child->text ** 2 );
                    }
                },
          },
        pretty_print => 'indented',
        );
    

    一旦您决定如何遍历 DOM,Twig 将处理细节以对其进行变异。

    【讨论】:

    • 谢谢。以后我会试试 XML::Twig。
    猜你喜欢
    • 1970-01-01
    • 2019-01-12
    • 2012-09-10
    • 1970-01-01
    • 1970-01-01
    • 2011-08-08
    • 2011-03-25
    • 1970-01-01
    • 2013-11-15
    相关资源
    最近更新 更多