2014-03-25 67 views
0

解析我有XML:複雜的XML與Perl和libxml的

<?xml version="1.0" encoding="UTF-8"?> 
<?xml-stylesheet type="text/xsl" href="MeasDataCollection.xsl"?> 

<measCollecFile xmlns=""> 
    <fileHeader fileFormatVersion="32.435 V7.2.0"> 
    </fileHeader> 

    <measData> 
     <managedElement localDn="bs=8" swVersion="R21A"/> 

     <measInfo measInfoId="CORE,SIP_session_statistics"> 
      <measType p="1">CPUUSAGE</measType> 
      <measType p="2">CPUMEM</measType> 
      <measType p="3">SYSMEM</measType> 

      <measValue measObjLdn="SGC.bsNo=17,networkRole=2"> 
       <r p="1">10</r> 
       <r p="2">20</r> 
       <r p="3">30</r> 
      </measValue> 

      <measValue measObjLdn="SGC.bsNo=18,networkRole=2"> 
       <r p="1">40</r> 
       <r p="2">50</r> 
       <r p="3">60</r> 
      </measValue> 
     </measInfo> 
    </measData> 
</measCollecFile> 

問題:

我想從<r p="1">40</r>元素提取40。唯一給出的是<measType p="1">CPUUSAGE</measType><measValue measObjLdn="SGC.bsNo=18,networkRole=2"> 即我只知道我需要找到bsNo=18CPUUSAGE。數據的順序始終保持不變。


這裏是我到目前爲止已經試過:

my $qry="//measInfo[measType/text() = 'CPUUSAGE']/measValue"; 

my @nodes= $conn->findnodes($qry); 

foreach my $vnode (@nodes) { 
    if ($vnode->getAttribute('measObjLdn') =~ /'bsNo=18'/) { 
     foreach my $node ($vnode) { 
      foreach my $p ($node->getChildnodes) { 
       if (ref($p)=~'Element'){ 
        $no=$p->textContent; 
        print $no;**#this prints the value of all the <r> elements** 
       } 
      } 
     } 
    } 
} 

我的挑戰是可以有很多元素,如CPUUSAGE,CPUMEM ...我如何能達到在正確的順序<r>對於給定的measValue屬性(/'bsNo=18'/)的順序元素。

並隨後修改40爲其他所需值**,因爲你對陣'bsNo=18'的屬性值,包括單引號

+2

你嘗試過這麼遠嗎?這對於單個XPath查詢來說很難做到,但解決此問題的方法並不複雜。 – amon

+0

@amon,'/ measCollecFile/measData/measInfo/measValue [@ measObjLdn =「SGC.bsNo = 18,networkRole = 2」]/r [@p = ../../measType[text()="CPUUSAGE「 ]/@ p]' – ikegami

+0

Catch:當只需要執行一次時,會導致對每個「r」執行'../../ measType [text()=「CPUUSAGE」]「。 – ikegami

回答

0

你的Perl代碼不能工作。

如果你想找到具有相同p屬性作爲CPUUSAGE節點r元素,你既可以嘗試通過池上或XPath表達式類似如下:

for my $type_node ($conn->findnodes('//measInfo/measType[.="CPUUSAGE"]')) { 
    my $p = $type_node->getAttribute('p'); 
    my $qry = <<"EOF"; 
.. 
/measValue[contains(concat(\@measObjLdn, ','), 'bsNo=18,')] 
/r[\@p='$p'] 
EOF 

    for my $r_node ($type_node->findnodes($qry)) { 
     print $r_node->textContent, "\n"; 
    }  
} 

這首先遍歷所有measType節點的內容爲CPUUSAGE,獲取p屬性,然後找到所有對應的r節點。這種方法應該比單個XPath查詢更有效。

要查找的位置r節點並修改其內容,請嘗試:

for my $type_node ($conn->findnodes('//measInfo/measType[.="CPUUSAGE"]')) { 
    my $pos = $type_node->findvalue('count(preceding-sibling::measType) + 1'); 
    my $qry = <<"EOF"; 
.. 
/measValue[contains(concat(\@measObjLdn, ','), 'bsNo=18,')] 
/r[$pos] 
EOF 

    for my $r_node ($type_node->findnodes($qry)) { 
     $r_node->removeChildNodes; 
     $r_node->appendText('50'); 
    } 
} 

print $conn->toString; 
+0

nwellnhof!這非常有幫助。 – marks

+0

萬一元素名稱是變量,那麼我無法找到節點。像//$measInfo/$measType[.="$CPUUSAGE「]。此外,當我試圖做精確匹配而不是包含然後以及它找不到節點。提前致謝。 – marks