Python lxml findall mit mehreren namespaces

Ich versuche, ein XML-Dokument mit mehreren Namespaces mit lxml zu analysieren, und ich stecke auf die findall () Methode, um etwas zurückzugeben.

Mein XML:

<MeasurementRecords xmlns="http://www.company.com/common/rsp/2012/07" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.company.com/common/rsp/2012/07 RSP_EWS_V1.6.xsd"> <HistoryRecords> <ValueItemId>100_0000100004_3788_Resource-0.customId_WSx Data Precip Type</ValueItemId> <List> <HistoryRecord> <Value>60</Value> <State>Valid</State> <TimeStamp>2016-04-20T12:40:00Z</TimeStamp> </HistoryRecord> </List> </HistoryRecords> <HistoryRecords> </MeasurementRecords> 

Mein Code:

 from lxml import etree from pprint import pprint RSPxmlFile = '/home/user/Desktop/100_0000100004_3788_20160420144011263_records.xml' with open (RSPxmlFile, 'rt') as f: tree = etree.parse(f) root = tree.getroot() for node in tree.findall('MeasurementRecords', root.nsmap): print node print "parameter = ", node.text 

Gibt:

 ValueError: empty namespace prefix is not supported in ElementPath 

Einige Experimente habe ich nach dem Lesen versucht:

 >>> root.nsmap {'xsi': 'http://www.w3.org/2001/XMLSchema-instance', None: http://www.company.com/common/rsp/2012/07'} >>> nsmap['foo']=nsmap[None] >>> nsmap.pop(None) 'http://www.company.com/common/rsp/2012/07' >>> nsmap {'xsi': 'http://www.w3.org/2001/XMLSchema-instance', 'foo': 'http://www.company.com/common/rsp/2012/07'} >>> tree.xpath("//MeasurementRecords", namespaces=nsmap) [] >>> tree.xpath('/foo:MeasurementRecords', namespaces=nsmap) [<Element {http://www.company.com/common/rsp/2012/07}MeasurementRecords at 0x6ffffda5290>] >>> tree.xpath('/foo:MeasurementRecords/HistoryRecords', namespaces=nsmap) [] 

Aber das schien nicht zu helfen.

Also mehr experimente:

 >>> tree.findall('//{http://www.company.com/common/rsp/2012/07}MeasurementRecords') [] >>> print root <Element {http://www.company.com/common/rsp/2012/07}MeasurementRecords at 0x6ffffda5290> >>> print tree <lxml.etree._ElementTree object at 0x6ffffda5368> >>> for node in tree.iter(): ... print node ... <Element {http://www.company.com/common/rsp/2012/07}MeasurementRecords at 0x6ffffda5290> <Element {http://www.company.com/common/rsp/2012/07}HistoryRecords at 0x6ffffda5cf8> <Element {http://www.company.com/common/rsp/2012/07}ValueItemId at 0x6ffffda5f38> ...etc... >>> tree.findall("//HistoryRecords", namespaces=nsmap) [] >>> tree.findall("//foo:MeasurementRecords/HistoryRecords", namespaces=nsmap) [] 

Ich bin stumped Ich habe keine Ahnung, was los ist

One Solution collect form web for “Python lxml findall mit mehreren namespaces”

Wenn du damit anfängst:

 >>> tree = etree.parse(open('data.xml')) >>> root = tree.getroot() >>> 

Das wird keine Elemente finden …

 >>> root.findall('{http://www.company.com/common/rsp/2012/07}MeasurementRecords') [] 

… aber das ist, weil root ein MeasurementRecords Element ist. Es enthält keine MeasurementRecords Elemente. Auf der anderen Seite funktioniert das folgende gut:

 >>> root.findall('{http://www.company.com/common/rsp/2012/07}HistoryRecords') [<Element {http://www.company.com/common/rsp/2012/07}HistoryRecords at 0x7fccd0332ef0>] >>> 

Mit der xpath Methode kannst du so etwas machen:

 >>> nsmap={'a': 'http://www.company.com/common/rsp/2012/07', ... 'b': 'http://www.w3.org/2001/XMLSchema-instance'} >>> root.xpath('//a:HistoryRecords', namespaces=nsmap) [<Element {http://www.company.com/common/rsp/2012/07}HistoryRecords at 0x7fccd0332ef0>] 

Damit:

  • Die findall und find Methoden erfordern {...namespace...}ElementName Syntax.
  • Die xpath Methode erfordert Namespace-Präfixe ( ns:ElementName ), die sie in der mitgelieferten namespaces Map ns:ElementName . Das Präfix muss nicht mit dem im Originaldokument verwendeten Präfix übereinstimmen, aber das Namespace-URL muss übereinstimmen.

So funktioniert das:

 >>> root.find('{http://www.company.com/common/rsp/2012/07}HistoryRecords/{http://www.company.com/common/rsp/2012/07}ValueItemId') <Element {http://www.company.com/common/rsp/2012/07}ValueItemId at 0x7fccd0332a70> 

Oder das funktioniert:

 >>> root.xpath('/a:MeasurementRecords/a:HistoryRecords/a:ValueItemId',namespaces=nsmap) [<Element {http://www.company.com/common/rsp/2012/07}ValueItemId at 0x7fccd0330830>] 
  • Parsing xml von python lxml tree.xpath
  • Scrapy xpath selecter wiederholt Daten
  • Populäre Python-Liste mit Daten aus dem Befehl lxml xpath
  • Volltextsuche XML-Daten mit Python: Best Practices, Pros & Contras
  • Sortieren von XML-Dateien
  • Anmeldung mit Webseiten
  • XPATH - html mit vielen Kindern
  • Python XPath / libxml2 Namespace Abfrage
  • OpenERP 7 Hinzufügen von Feld zu vorhandenem Modul - XML ​​Validate Error
  • Parse xml mit lxml - Extrakt Element Wert
  • Erstellen von Loop, um Tabellendaten in scrapy / python zu analysieren
  • Python ist die beste Programmiersprache der Welt.