2010-08-04 6 views
0

Mon fichier XML ressemble à ceci:Comment puis-je changer la valeur du paramètre en XML en utilisant Perl?

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

Je voudrais changer la valeur <Item Value="NONE"/>-<Item Value="API"/> sous <Parameter Name="MapSource">.

+1

Avez-vous un processeur XSLT disponible? C'est trivial en XSL. –

Répondre

0

Se souvenant que le traitement XML avec des expressions régulières est usually a really bad idea, avec Perl vous pourriez

#! /usr/bin/perl 

use warnings; 
use strict; 

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

et fix.xsl de

<?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> 

pour obtenir le résultat souhaité:

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

En Si vous n'êtes pas familier, <(./prog.pl) utilise bash process substitution, donc la commande diff compare input.xml avec la sortie du programme court Perl.

Pour remplacer tous les éléments d'élément qui sont des descendants des paramètres MapSource, utilisez la feuille de style ci-dessous. Notez à quel point la structure du document source est plus flexible.

<?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> 

Maintenant, le changement de l'entrée à la sortie est

$ 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

J'ai adoré cette solution. Je vous remercie. Q: Comment je peux changer le fichier fix.xsl pour éviter d'utiliser 'NONE' dans le chemin [@ Value = 'NONE']. Je ne veux pas m'inquiéter quelle chaîne occupe actuellement Toren

+0

@Toren Merci! Voir la mise à jour –

0

Le moyen le plus rapide (plus facile) que j'ai trouvé XML::XPath (encore plus petit avec File::Slurp - voir l'historique des modifications pour le code pré-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

Merci. Belle solution – Toren

Questions connexes