1

问这个问题感觉很愚蠢,但到目前为止已经浪费了整个下午,而且离解决方案还差得远。我正在自动推出一些 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>

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

而且代码应该比较简单:

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;

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

4

2 回答 2

2

这是一个XML::Twigstring程序,它将删除a.

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 将处理细节以改变它。

于 2012-04-18T18:00:04.087 回答
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”,并且“选择”节点下只有一个节点。然后,您可以使用 再次打印出 XML print $d->toString();

于 2012-04-18T18:45:06.133 回答