如何使用Perl更改XML中的参数值?

时间:2010-08-04 16:04:00

标签: xml perl

我的XML文件如下所示:

<Configuration>
    <Parameters>
        <Component Name="Aas">
            <Group Name="PrivilegesMapping">
                <Parameter Name="PrivilegesLoaderInterval">
                    <Description>
                    The interval (in minute) 
                    </Description>
                    <Type>Integer</Type>
                    <Restriction>
                        <RequiresRestart>true</RequiresRestart>
                        <MinVal/>
                        <MaxVal/>
                        <MaxLength/>
                        <Mandatory>true</Mandatory>
                        <Lov/>
                        <Level>5</Level>
                    </Restriction>
                    <Value>
                        <Item Value="5"/>
                    </Value>
                </Parameter>
            </Group>
            <Group Name="DomainsMapping">
                <Parameter Name="DomainLoaderInterval">
                    <Description>
                    The interval (in minute) 
                    </Description>
                    <Type>Integer</Type>
                    <Restriction>
                        <RequiresRestart>true</RequiresRestart>
                        <MinVal/>
                        <MaxVal/>
                        <MaxLength/>
                        <Mandatory>true</Mandatory>
                        <Lov/>
                        <Level>5</Level>
                    </Restriction>
                    <Value>
                        <Item Value="5"/>
                    </Value>
                </Parameter>
                <Parameter Name="MapSource">
                    <Description>
                    Set the source of the domains list
                    </Description>
                    <Type>Enum</Type>
                    <Restriction>
                        <RequiresRestart>true</RequiresRestart>
                        <MinVal/>
                        <MaxVal/>
                        <MaxLength/>
                        <Mandatory>true</Mandatory>
                        <Lov>
                            <Val>FILE</Val>
                            <Val>DATABASE</Val>
                            <Val>NONE</Val>
                        </Lov>
                        <Level>5</Level>
                    </Restriction>
                    <Value>
                        <Item Value="FILE"/>
                    </Value>
                </Parameter>
            </Group>
            <Group Name="SystemsMapping">
                <Parameter Name="MapSource">
                    <Description>
                    </Description>
                    <Type>Enum</Type>
                    <Restriction>
                        <RequiresRestart>true</RequiresRestart>
                        <MinVal/>
                        <MaxVal/>
                        <MaxLength/>
                        <Mandatory>true</Mandatory>
                        <Lov>
                            <Val>API</Val>
                            <Val>FILE</Val>
                            <val>NONE</Val>
                        </Lov>
                        <Level>5</Level>
                    </Restriction>
                    <Value>
                        <Item Value="NONE"/>
                    </Value>
                </Parameter>
                <Parameter Name="SystemsLoaderInterval">
                    <Description>
                    The interval (in minute) 
                    </Description>
                    <Type>Integer</Type>
                    <Restriction>
                        <RequiresRestart>true</RequiresRestart>
                        <MinVal/>
                        <MaxVal/>
                        <MaxLength/>
                        <Mandatory>true</Mandatory>
                        <Lov/>
                        <Level>5</Level>
                    </Restriction>
                    <Value>
                        <Item Value="5"/>
                    </Value>
                </Parameter>
            </Group>
        </Component>
    </Parameters>
</Configuration>

我想将<Item Value="NONE"/>下的值更改为<Item Value="API"/>下的<Parameter Name="MapSource">

2 个答案:

答案 0 :(得分:0)

记住使用正则表达式处理XML是usually a really bad idea,使用Perl可以

#! /usr/bin/perl

use warnings;
use strict;

system("xsltproc", "fix.xsl", "input.xml") == 0
  or warn "$0: xsltproc failed\n";

和<{p>}的fix.xsl

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="/Configuration/Parameters/Component/Group/Parameter[@Name='MapSource']/Value/Item[@Value='NONE']">
    <xsl:element name="Item">
      <xsl:attribute name="Value">API</xsl:attribute>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

获得所需的结果:

$ diff -ub input.xml <(./prog.pl)
--- input.xml
+++ /dev/fd/63
@@ -1,3 +1,4 @@
+<?xml version="1.0"?>
 <Configuration>
     <Parameters>
         <Component Name="Aas">
@@ -82,7 +83,7 @@
                         <Level>5</Level>
                     </Restriction>
                     <Value>
-                        <Item Value="NONE"/>
+                        <Item Value="API"/>
                     </Value>
                 </Parameter>
                 <Parameter Name="SystemsLoaderInterval">

如果您不熟悉,<(./prog.pl)使用bash process substitution,那么diff命令会将input.xml输出进行比较简短的Perl计划。

要替换作为MapSource参数后代的所有Item元素,请使用下面的样式表。请注意它对源文档的结构更加灵活。

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="//Parameter[@Name='MapSource']//Item">
    <xsl:element name="Item">
      <xsl:attribute name="Value">API</xsl:attribute>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

现在从输入到输出的变化是

$ diff -ub input.xml <(./prog.pl)
--- input.xml
+++ /dev/fd/63
@@ -1,3 +1,4 @@
+<?xml version="1.0"?>
 <Configuration>
     <Parameters>
         <Component Name="Aas">
@@ -59,7 +60,7 @@
                         <Level>5</Level>
                     </Restriction>
                     <Value>
-                        <Item Value="FILE"/>
+                        <Item Value="API"/>
                     </Value>
                 </Parameter>
             </Group>
@@ -82,7 +83,7 @@
                         <Level>5</Level>
                     </Restriction>
                     <Value>
-                        <Item Value="NONE"/>
+                        <Item Value="API"/>
                     </Value>
                 </Parameter>
                 <Parameter Name="SystemsLoaderInterval">

答案 1 :(得分:0)

我找到的最快(最简单)的方法是XML::XPathFile::Slurp更小 - 请参阅预诽谤代码的编辑历史记录):

use strict;
use warnings;
use File::Slurp ();
use XML::XPath;
use XML::XPath::XMLParser;

my $path = '/path/to/file/config.xml';
my $xp   = XML::XPath->new( filename => $path );
$xp->setNodeText( q{//Parameter[@Name='MapSource']/Value/Item/@Value} 
                , 'API'
                );
File::Slurp::write_file( $path, $xp->findnodes_as_string( '/' ));