2016-07-18 23 views
4

Ich wollte Xpath jedes Elements in XML-Datei erhalten.Wie bekomme ich xpath aller Elemente in XML-Datei mit Standard-Namespace mit Python?

XML-Datei:

<root 
xmlns="http://www.w3.org/TR/html4/" 
xmlns:h="http://www.w3schools.com/furniture"> 

<table> 
    <tr> 
    <h:td>Apples</h:td> 
    <h:td>Bananas</h:td> 
    </tr> 
</table> 
</root> 

Python-Code: Da null Präfix in Standard-Namespace nicht erlaubt ist, habe ich mein eigenes Präfix dafür.

from lxml import etree 
root=etree.parse(open("MyData.xml",'r')) 
ns={'df': 'http://www.w3.org/TR/html4/', 'types': 'http://www.w3schools.com/furniture'} 
for e in root.iter(): 
    b=root.getpath(e) 
    print b 
    r=root.xpath(b,namespaces=ns) 
    #i need both b and r here 

der XPath ist so (Ausgabe b)

/* 
/*/*[1] 
/*/*[1]/*[1] 
/*/*[1]/*[1]/h:td 

i nicht den XPath richtig für Elemente mit Standard-Namespace erhalten können, zeigt es als * für diejenigen Elemente Namen. Wie bekomme ich xpath richtig?

Antwort

1

Sie könnten getelementpath verwenden, die immer die Elemente in Clark Notation zurückgibt, und ersetzen Sie die Namespaces manuell:

x = """ 
<root 
xmlns="http://www.w3.org/TR/html4/" 
xmlns:h="http://www.w3schools.com/furniture"> 

<table> 
    <tr> 
    <h:td>Apples</h:td> 
    <h:td>Bananas</h:td> 
    </tr> 
</table> 
</root> 
""" 

from lxml import etree 
root = etree.fromstring(x).getroottree() 
ns = {'df': 'http://www.w3.org/TR/html4/', 'types': 'http://www.w3schools.com/furniture'} 
for e in root.iter(): 
    path = root.getelementpath(e) 
    root_path = '/' + root.getroot().tag 
    if path == '.': 
     path = root_path 
    else: 
     path = root_path + '/' + path 
    for ns_key in ns: 
     path = path.replace('{' + ns[ns_key] + '}', ns_key + ':') 
    print(path) 
    r = root.xpath(path, namespaces=ns) 
    print(r) 

Offensichtlich ist dieses Beispiel zeigt, dass getelementpath kehrt Pfade relativ zum Wurzelknoten, wie . und dt:table anstelle von /df:root und /df:root/df:table, so verwenden wir die tag des Wurzelelements, um den vollständigen Pfad manuell zu erstellen.

Ausgang:.

/df:root 
[<Element {http://www.w3.org/TR/html4/}root at 0x37f5348>] 
/df:root/df:table 
[<Element {http://www.w3.org/TR/html4/}table at 0x44bdb88>] 
/df:root/df:table/df:tr 
[<Element {http://www.w3.org/TR/html4/}tr at 0x37fa7c8>] 
/df:root/df:table/df:tr/types:td[1] 
[<Element {http://www.w3schools.com/furniture}td at 0x44bdac8>] 
/df:root/df:table/df:tr/types:td[2] 
[<Element {http://www.w3schools.com/furniture}td at 0x44bdb88>] 
+0

--die Code funktioniert gut, aber stattdessen xml aus Zeichenfolge zu lesen, mag ich es aus einer XML-Datei wie offen lesen ("MyData.xml", 'r') i kenne die genaue Syntax für root = etree.fromstring (x) .getroottree() nicht, um das Lesen von Dateien zu unterstützen. Wie geht das? – mariz

+0

@mariz, um eine Datei mit dem Namen 'MyData.xml' zu parsen, können Sie' root = etree.fromstring (x) .getroottree() 'durch' root = etree.parse ('MyData.xml') ersetzen. Weitere Informationen unter: http://lxml.de/parsing.html –