2017-05-24 23 views
2

XML :: LibXML을 사용하는 데 문제가 있으며 원하는 작업을 수행 할 수있는 방법이 있는지 또는 XML을 변경해야하는지 알고 싶습니다. 당신이 볼 수 있듯이, "행동"에, 행동 (1 또는 각 종류의 여러 작업의 다른 유형이있을 수Perl XML :: LibXML 사용

<fftg> 
    <actions> 

      <rename> 
        <mandatory>0</mandatory> 
        <other_things_here /> 
      </rename> 

      <transfer> 
        <mandatory>0</mandatory> 
        <protocol>SFTP</protocol> 
        <other_things_here /> 
      </transfer> 

      <transfer> 
        <mandatory>1</mandatory> 
        <protocol>FTP</protocol> 
        <other_things_here /> 
      </transfer> 

      <archive> 
        <mandatory>1</mandatory> 
        <other_things_here /> 
      </archive> 

      <rename> 
        <mandatory>1</mandatory> 
        <other_things_here /> 
      </rename> 

    </actions> 

</fftg> 

에 따라 여러 가지로, : 같은 순간에

내 XML 보인다 각 동작)

각 동작을 탐색하고 동작에 따라 특정 작업을 수행하려고합니다.

내 문제는 : 같은 종류의 여러 작업이 있기 때문에 스크립트가 제대로 작동하지 않으며 같은 종류의 이전 작업을 덮어 쓰거나 특정 작업의 루프가 같은 작업의 모든 루프를 반복합니다. 종류

예 1 :

foreach my $transfer ($doc->findnodes('/fftg')) { 

    # Browse Actions 
    foreach my $action ($doc->findnodes('/fftg/actions/*')) { 

      my $action_name = $action->nodeName(); 
      my $actiontype = ucfirst($action->nodeName()); 
      print "executing action $action_name ..\n"; 

      # Browse action details 
      foreach my $action_details ($doc->findnodes('/fftg/actions/'.$action_name)) { 
        for my $detail ($action_details->findnodes('./*')) { 
          print $detail->nodeName(), ": ", $detail->textContent(), "\n"; 
        } 
      } 
      print "-------------\n"; 
    } 
} 

결과 1 :

executing action rename .. 
mandatory: 0 
other_things_here: 
mandatory: 1 
other_things_here: 
------------- 
executing action transfer .. 
mandatory: 0 
protocol: SFTP 
other_things_here: 
mandatory: 1 
protocol: FTP 
other_things_here: 
------------- 
executing action transfer .. 
mandatory: 0 
protocol: SFTP 
other_things_here: 
mandatory: 1 
protocol: FTP 
other_things_here: 
------------- 
executing action archive .. 
mandatory: 1 
other_things_here: 
------------- 
executing action rename .. 
mandatory: 0 
other_things_here: 
mandatory: 1 
other_things_here: 
------------- 

당신이 볼 수 있듯이,이 결과는 좋은 드 (각 "동작 유형"에서와 같이 잘못 tected), 같은 종류의 모든 액션에 대해 반복됩니다.

이 때문이다

foreach my $action_details ($doc->findnodes('/fftg/actions/'.$action_name)) { 

어떻게 내가 무엇을 달성하고자하기 위해 무엇을 할 수 있는가?

내가 원하는 것은 (XML을 변경하지 않고 가능하면) :

executing action rename .. 
mandatory: 0 
other_things_here: 
------------- 
executing action transfer .. 
mandatory: 0 
protocol: SFTP 
other_things_here: 
------------- 
executing action transfer .. 
mandatory: 1 
protocol: FTP 
other_things_here: 
------------- 
executing action archive .. 
mandatory: 1 
other_things_here: 
------------- 
executing action rename .. 
mandatory: 1 
other_things_here: 
------------- 

가 보조 노트에 당신에게

감사합니다, 나는 내 XML을 변경하고 대신 해결하기 위해 그런 일을 사용할 수도있을 것 같군요 쉽게 (그러나 어느 것이 3 가지 중에서 가장 좋은 옵션인지는 모르겠지만) XSD가 이후에 생성하기가 어려울 것이므로 아래 두 가지를 피하고 싶습니다. (각 액션 유형에 대한 특정 옵션을 원합니다.) :

<fftg> 
<actions> 
     <action> 
       <type>rename</type> 
       <mandatory>0</mandatory> 
       <other_things_here /> 
     </action> 

     <action> 
       <type>transfer</type> 
       <mandatory>0</mandatory> 
       <protocol>SFTP</protocol> 
       <other_things_here /> 
     <action> 

     <action> 
       <type>transfer</type> 
       <mandatory>0</mandatory> 
       <protocol>FTP</protocol> 
       <other_things_here /> 
     <action> 

     <action> 
       <type>archive</type> 
       <mandatory>0</mandatory> 
       <other_things_here /> 
     <action> 

     <action> 
       <type>rename</type> 
       <mandatory>0</mandatory> 
       <other_things_here /> 
     <action> 



</actions> 

</fftg> 

또는

<fftg> 
<actions> 
     <action type="rename"> 
       <mandatory>0</mandatory> 
       <other_things_here /> 
     </action> 

     <action type="transfer"> 
       <mandatory>0</mandatory> 
       <protocol>SFTP</protocol> 
       <other_things_here /> 
     <action> 

     <action type="transfer"> 
       <mandatory>0</mandatory> 
       <protocol>FTP</protocol> 
       <other_things_here /> 
     <action> 

     <action type="archive"> 
       <mandatory>0</mandatory> 
       <other_things_here /> 
     <action> 

     <action type="rename"> 
       <mandatory>0</mandatory> 
       <other_things_here /> 
     <action> 



</actions> 

</fftg> 

덕분에 다시

+0

... 다른 질문에 당신이 속성을 가지고''내부 요소를 가지고 : 두 개의 루프 (<action/> 아이들에 하나, 그리고 자녀에 대한 또 하나) 작동합니다. 그것은 사물을 바꿀 수도 있으므로 여기서도 언급 할 가치가 있습니다. – simbabque

답변

4

먼저 에 관해서는, 당신은 당신의 XPath 표현식은 문서 루트 노드에 대해 평가 의미 $docfindnodes를 호출합니다. 둘째, 사용하는 XPath 표현식은 '/'로 시작하므로 다시 최상위 노드에 뿌리를두고 있습니다. 전화 할 때, 너무 :

$doc->findnodes('/fftg/actions/rename') 

그 의미 결과로, 그리고 "나에게 문서의 루트 노드입니다 <fftg/> 요소의 아이가 <actions/> 요소의 아이가있는 모든 <rename/> 요소를 제공합니다", 당신은 얻을 노드에있는 모든 <rename/>은 문서에 있습니다.

또한 루프가 너무 많습니다. 첫 번째 요소는 중복되어 하나의 루트 요소 만있을 수 있습니다.이 모든 읽기 전에

for my $action ($doc->findnodes('/fftg/actions/*')) { 
    print "executing ", $action->nodeName(), "\n"; 
    for my $detail ($action->findnodes('./*')) { 
     print $detail->nodeName(), ": ", $detail->textContent(), "\n"; 
    } 
}