2010-08-04 2 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="API"/><Item Value="NONE"/>에서 값을 변경하고 싶습니다. 정규 표현식이 처리 XML을 기억

+1

XSLT 프로세서를 사용할 수 있습니까? 이것은 XSL에서 사소한 일입니다. –

답변

0

펄, usually a really bad idea 당신 수

#! /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> 

지금 입력에서 출력의 변화는 내가 찾은 가장 빠른 (쉬운) 방법 (File::Slurp와 더 작은 - 사전 소리내어 먹는다 코드에 대한 편집 기록을 참조) XML::XPath했다

$ 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

나는이 해결책을 좋아했다. 고맙습니다. Q : 경로 [@ Value = 'NONE']에서 'NONE'을 사용하지 않도록 fix.xsl을 어떻게 변경할 수 있습니까? 나는 현재 어떤 문자열이 점재하고 싶지 않다. Toren

+0

@Toren 고마워! 업데이트 된 답변보기 –

0

입니다 :

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

관련 문제