2016-08-14 3 views
0

Ich habe versucht, einige XML für ein paar Stunden jetzt ohne Glück zu analysieren. Überprüft ähnliche Threads und überprüft die ElementTree-Dokumente und noch ziemlich verloren.ElementTree: Parsing XML-Urenkel

Grundsätzlich erhalte ich einige XML-Ausgabe von einem Router, der in einer Zeichenfolge gespeichert ist, die ich wiederum für bestimmte Informationen analysieren muss.

Hier eine Probe des xml ist arbeite ich an:

xml = """<rpc-reply xmlns:junos="http://xml.juniper.net/junos/14.1D0/junos"> 
     <route-information xmlns="http://xml.juniper.net/junos/14.1D0/junos-routing"> 
      <!-- keepalive --> 
      <route-table> 
       <table-name>inet.0</table-name> 
       <destination-count>52</destination-count> 
       <total-route-count>52</total-route-count> 
       <active-route-count>52</active-route-count> 
       <holddown-route-count>0</holddown-route-count> 
       <hidden-route-count>0</hidden-route-count> 
       <rt junos:style="brief"> 
        <rt-destination>5.5.5.5/32</rt-destination> 
        <rt-entry> 
         <active-tag>*</active-tag> 
         <current-active/> 
         <last-active/> 
         <protocol-name>Direct</protocol-name> 
         <preference>0</preference> 
         <age junos:seconds="428929">4d 23:08:49</age> 
         <nh> 
          <selected-next-hop/> 
          <via>lo0.0</via> 
         </nh> 
        </rt-entry> 
       </rt> 
      </route-table> 
     </route-information> 
     <cli> 
      <banner></banner> 
     </cli> 
</rpc-reply>""" 

Zum Beispiel kann der Knoten Ich mag würde bekommen Inhalt/Druck auf die rt-Ziel.

Ich habe versucht:

root = ET.fromstring(xml) 

values = root.find('rt') 
for element in values: 
    print element.text 

Diese

value= root.find('rt-destination') 

print value 

Und diese Wurzel zu setzen (Zeiger?) An dem bestimmten Knoten,

x = root.getiterator(tag = "destination-count") 

Jede Hilfe in Bezug auf, wie man Überqueren Sie diesen spezifischen Knoten oder wie Sie zum gewünschten Ergebnis gelangen, wäre sehr willkommen.

Antwort

1

Ihnen fehlt der Namensraum für das route-information-Tag. In Ihrem XML haben Sie 2 Namespaces, leider ist der von Ihnen benötigte nicht etikettiert.

<rpc-reply xmlns:junos="http://xml.juniper.net/junos/14.1D0/junos"> 
    <route-information xmlns="http://xml.juniper.net/junos/14.1D0/junos-routing"> 

rpc-reply fallen unter die Namespace junos jedoch die nächste Schicht und alles unter ihm unter dem unbenannte (null) Namespace fällt xmlns="http://xml.juniper.net/junos/14.1D0/junos-routing".

mit root.nsmap gibt das folgende Namespace-Wörterbuch für die Root-Ebene: {'junos': 'http://xml.juniper.net/junos/14.1D0/junos'}. So rt Elemente in diesem Namensraum zugreifen möchten Sie verwenden:

root.find('junos:rt', namespaces=root.nsmap) 

jedoch in der nächsten Schicht ist lxml.etree sich der Namespace "http://xml.juniper.net/junos/14.1D0/junos-routing", sondern weil es kein Label hat, extrahiert sie es auf den Namespace-Karte mit None als der Wörterbuchschlüssel.

>>> nsmap = root.getchildren()[0].nsmap 
>>> nsmap 
{'junos': 'http://xml.juniper.net/junos/14.1D0/junos', 
None: 'http://xml.juniper.net/junos/14.1D0/junos-routing'} 

Nun, das ist ein Problem, weil wir den Namespace None nicht verweisen können. Eine Option besteht darin, im Wörterbuch für 'http://xml.juniper.net/junos/14.1D0/junos-routing' einen neuen Namespace-Verweis zu erstellen.

nsmap['my_ns'] = nsmap.pop(None) 

Wir brauchen .pop hier zu verwenden, da lxml nicht die Verwendung eines mit None als Schlüssel Namensraum ermöglichen. Jetzt können Sie mithilfe von xpath nach dem Tag rt-destination suchen und nur den Text innerhalb des Tags zurückgeben.

root.xpath('.//my_ns:rt-destination/text()', namespaces=nsmap) 
1

Der Grund, warum der Code nicht funktioniert, liegt am Namensraum. Wenn der Namespace immer die gleiche ist, können Sie es als Präfix für den Tag-Code Sie zu finden sind versuchen:

import xml.etree.ElementTree as ET 

xml = """ 
<rpc-reply xmlns:junos="http://xml.juniper.net/junos/14.1D0/junos"> 
    <route-information xmlns="http://xml.juniper.net/junos/14.1D0/junos-routing"> 
     <!-- keepalive --> 
     <route-table> 
      <table-name>inet.0</table-name> 
      <destination-count>52</destination-count> 
      <total-route-count>52</total-route-count> 
      <active-route-count>52</active-route-count> 
      <holddown-route-count>0</holddown-route-count> 
      <hidden-route-count>0</hidden-route-count> 
      <rt junos:style="brief"> 
       <rt-destination>5.5.5.5/32</rt-destination> 
       <rt-entry> 
        <active-tag>*</active-tag> 
        <current-active/> 
        <last-active/> 
        <protocol-name>Direct</protocol-name> 
        <preference>0</preference> 
        <age junos:seconds="428929">4d 23:08:49</age> 
        <nh> 
         <selected-next-hop/> 
         <via>lo0.0</via> 
        </nh> 
       </rt-entry> 
      </rt> 
     </route-table> 
    </route-information> 
    <cli> 
     <banner></banner> 
    </cli> 
</rpc-reply> 
""" 

XML_NAMESPACE = '{http://xml.juniper.net/junos/14.1D0/junos-routing}' 
root = ET.fromstring(xml) 
rt_nodes = root.iter(tag='{}rt-destination'.format(XML_NAMESPACE)) 
print rt_nodes.next().text # 5.5.5.5/32 

Wenn Sie etwas flexibler benötigen, können Sie die Antworten überprüfen here.