2010-08-04 69 views
0

我的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> 

我想<Parameter Name="MapSource">下从<Item Value="NONE"/>改变价值<Item Value="API"/>

+1

您是否有可用的XSLT处理器?这在XSL中是微不足道的。 – 2010-08-04 16:39:30

回答

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"; 

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">
+0

我喜欢这个解决方案。谢谢。 问:我如何更改fix.xsl以避免在路径中使用'NONE'[@ Value ='NONE']。我不想在乎目前占用什么字符串 Toren 2010-08-05 10:02:18

+0

@Toren谢谢!查看更新的答案。 – 2010-08-05 16:26:55

0

最快(最简单的)方式,我发现XML::XPath(即使File::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('/')); 
+0

谢谢。好的解决方案 – Toren 2010-08-05 21:53:05