我的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">
。
答案 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::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( '/' ));