2017-02-04 3 views
2

J'ai lu une tonne de threads sur xpath & lxml, mais il me semble encore manquer quelque chose en ce qui concerne le xml suivant.python xpath retourne la liste vide

J'ai besoin de tirer l'élément 'rt-entry', ainsi que les informations qu'il contient.

Je cherche les éléments suivants en python:

from lxml import etree 

x=""" 
<rpc-reply xmlns:junos="http://xml.juniper.net/junos/12.3R5/junos"> 
    <route-information xmlns="http://xml.juniper.net/junos/12.3R5/junos-routing"> 
     <route-table> 
      <table-name>x.inet.0</table-name> 
      <destination-count>4990</destination-count> 
      <total-route-count>51326</total-route-count> 
      <active-route-count>4990</active-route-count> 
      <holddown-route-count>0</holddown-route-count> 
      <hidden-route-count>0</hidden-route-count> 
      <rt junos:style="detail"> 
       <rt-destination>x.x.x.x</rt-destination> 
       <rt-prefix-length>14</rt-prefix-length> 
       <rt-entry-count junos:format="2 entries">2</rt-entry-count> 
       <rt-announced-count>1</rt-announced-count> 
       <tsi junos:indent="0"> 
        KRT in-kernel x.x.x.x/x -> {indirect(x)} 
        Page 0 idx 0 Type 1 val b4557d8 
         Flags: Nexthop Change 
         Nexthop: Self 
         Localpref: 100 
         AS path: [x] I 
        Path x.x.x.x from x.x.x.x Vector len 4. Val: 0 
       </tsi> 
       <rt-entry> 
        <active-tag>*</active-tag> 
        <current-active/> 
        <last-active/> 
        <protocol-name>BGP</protocol-name> 
        <preference>170</preference> 
        <preference2>-101</preference2> 
        <nh-type>Indirect</nh-type> 
        <nh-address>x</nh-address> 
        <nh-reference-count>123</nh-reference-count> 
        <nh-kernel-id>0</nh-kernel-id> 
        <gateway>x.x.x.x</gateway> 
        <nh-type>Router</nh-type> 
        <nh-index>1538</nh-index> 
        <nh junos:indent="16"> 
         <nh-string>Next hop</nh-string> 
         <to>x.x.x.x</to> 
         <via>x.x</via> 
         <selected-next-hop/> 
         <session>63</session> 
        </nh> 
        <protocol-nh junos:indent="16"> 
         <to>x.x.x.x</to> 
         <indirect-nh>bac2c40 1048576 INH Session ID: 0xa7</indirect-nh> 
        </protocol-nh> 
        <rt-entry-state>Active Int Ext</rt-entry-state> 
        <peer-as>x</peer-as> 
        <announce-bits>3</announce-bits> 
        <announce-tasks>0-KRT 2-BGP_RT_Background 3-Resolve tree 7 </announce-tasks> 
        <as-path>AS path: I 
        </as-path> 
        <bgp-rt-flag>Accepted</bgp-rt-flag> 
        <local-preference>100</local-preference> 
        <peer-id>x.x.x.x</peer-id> 
        <indirect-nh-count>1</indirect-nh-count> 
        <protocol-nh junos:indent="24"> 
         <to>x.x.x.x</to> 
         <indirect-nh>bac2c40 1048576 INH Session ID: 0xa7</indirect-nh> 
         <forwarding-nh-count>1</forwarding-nh-count> 
         <nh-type>Router</nh-type> 
         <nh-index>1538</nh-index> 
         <nh junos:indent="8"> 
          <nh-string>Next hop</nh-string> 
          <to>x.x.x.x</to> 
          <via>x.x</via> 
          <session>63</session> 
         </nh> 
         <output> 
             x.x.x.x/x Originating RIB: x.inet.0 
              Node path count: 1 
              Forwarding nexthops: 1 
              Next hop type: Interface 
              Nexthop: via x.x 
         </output> 
        </protocol-nh> 
       </rt-entry> 
      </rt> 
     </route-table> 
    </route-information> 
    <cli> 
     <banner>{master}</banner> 
    </cli> 
</rpc-reply> 
""" 

root=etree.fromstring(x) 
print(root.xpath('//rt-entry[current-active]')) 

Cependant, je reçois une liste vide. Soit mon xpath est faux, soit j'utilise incorrectement lxml.

Toute aide est appréciée.

Répondre

2

La déclaration xmlns:junos="http://xml.juniper.net/junos/12.3R5/junos" figurant dans l'élément racine rpc-reply de votre source XML place le document entier dans un espace de noms.

Donc, vous devez soit utiliser une expression XPath espace de nom, ou bien il suffit d'utiliser local-name():

print(root.xpath('//*[local-name() = "rt-entry"][*[local-name() = "current-active"]]')) 
4

Essayez d'utiliser des préfixes d'espaces de noms:

print (root.xpath('//junos-routing:rt-entry',namespaces={"junos-routing":"http://xml.juniper.net/junos/12.3R5/junos-routing"})) 

ref: http://lxml.de/xpathxslt.html

+0

Upvoted, il est préférable de déclarer cet espace de noms dans une dict que de l'ignorer avec 'local-name()'. –

+0

Merci pour l'aide, cela a résolu pour moi. Y at-il un moyen facile de capturer l'espace de noms via lxml? Pour l'instant je ne fais que transformer l'entrée racine en une chaîne et la diviser. – Dayde

+0

@Dayde Je n'ai pas de meilleure solution, boucle les éléments enfants pour obtenir des espaces de noms? 'pour elem dans root.getchildren(): print elem.nsmap' – TopCaver