2016-06-14 4 views
1

Ich habe eine einzelne XML-Datei, die wie folgt formatiert ist:mehrere XML-Dateien von einem

<Main1> 
    <Sub1> 
    <Name>Test</Name> 
    <ID>12345</ID> 
    <Sub2> 
     <Prop> 
     <Key>A</Key> 
     <Value>Apple</Value> 
     </Prop> 
     <Prop> 
     <Key>B</Key> 
     <Value>Ball</Value> 
     </Prop> 
    </Sub2> 
    <Sub3> 
     <Order> 
     <OID>54321</OID> 
     <ODate>2016-01-01</ODate> 
     </Order> 
    </Sub3> 
    </Sub1> 
</Main1> 

Ich versuche, diese XML-Python-Import zu haben, und teilen sie in drei verschiedene Dateien: eine Datei für die Personen, Name und ID, eine Datei für die Eigenschaften und eine Datei für die Bestellinformationen. Wenn ich es jedoch teile, möchte ich die Kunden-ID zur Property- und Order-Datei hinzufügen. So ist die Property-Datei kann am Ende aussehen wie:

<Orders> 
    <Order> 
    <ID>12345</ID> 
    <OID>54321</OID> 
    <ODate>2016-01-01</ODate> 
    </Order> 
</Orders> 
+0

XML erlaubt nur einen einzelnen Wurzelknoten in einem Dokument - wie würde also die Eigenschaftendatei aussehen, da es anscheinend mehrere '' Knoten gibt? –

+0

Ich entschuldige mich dafür. Die Wurzel wäre "Bestellungen", wobei jede "Bestellung" ein anderer Knoten wäre. – NLMDEJ

+0

Und das gleiche für '' ich nehme an? –

Antwort

3

Verwenden lxml und element.xpath(), um die Knoten zu wählen Sie brauchen, und hängen Sie sie an Knoten in neue XML-Dokumente, wie Sie benötigen.

XPath ist kein Konzept, das von lxml eingeführt wird, sondern eine allgemeine Abfragesprache zum Auswählen von Knoten aus einem XML-Dokument, das von vielen Dingen unterstützt wird, die sich mit XML befassen. Betrachten Sie es als etwas ähnlich wie CSS-Selektoren, aber leistungsfähiger (auch ein bisschen komplizierter). Siehe XPath Syntax.

So zum Beispiel

tree.xpath('/Main1/Sub1') 

würde wählen Sie das <Sub1 /> Element direkt unter dem <Main1 /> Knoten.

Beachten Sie, dass .xpath() immer eine Liste ausgewählter Knoten zurückgibt - wenn Sie also nur einen Konto haben möchten.

Also, so etwas wie dies funktionieren sollte:

from copy import copy 
from lxml import etree 


def parse(filename): 
    parser = etree.XMLParser(remove_blank_text=True) 
    root = etree.parse(open(filename), parser=parser) 
    return root 


def dump_to_file(root, filename_base, id_): 
    customer_id = id_.text.strip() 
    filename = '%s-%s.xml' % (filename_base, customer_id) 
    with open(filename, 'w') as xml_file: 
     etree.ElementTree(root).write(xml_file, pretty_print=True) 


def dump_orders(id_, orders): 
    root = etree.XML('<Orders/>') 
    for order in orders: 
     order.append(copy(id_)) 
     root.append(order) 
    dump_to_file(root, 'orders', id_) 


def dump_properties(id_, properties): 
    root = etree.XML('<Properties/>') 
    for prop in properties: 
     prop.append(copy(id_)) 
     root.append(prop) 
    dump_to_file(root, 'properties', id_) 


def dump_customer(id_, name): 
    root = etree.XML('<Customer/>') 
    root.append(copy(id_)) 
    root.append(copy(name)) 
    dump_to_file(root, 'customer', id_) 


root = parse('complete.xml') 
customers = root.xpath('/Main1/Sub1') 

for customer in customers: 
    name = customer.xpath('./Name')[0] 
    id_ = customer.xpath('./ID')[0] 
    dump_customer(id_, name) 

    properties = customer.xpath('./Sub2/Prop') 
    dump_properties(id_, properties) 

    orders = customer.xpath('./Sub3/Order') 
    dump_orders(id_, orders) 

Diese drei Dateien wie diese pro Kunde schaffen:

customer-12345.xml

<Customer> 
    <ID>12345</ID> 
    <Name>Test</Name> 
</Customer> 

orders-12345.xml

properties-12345.xml

<Properties> 
    <Prop> 
    <Key>A</Key> 
    <Value>Apple</Value> 
    <ID>12345</ID> 
    </Prop> 
    <Prop> 
    <Key>B</Key> 
    <Value>Ball</Value> 
    <ID>12345</ID> 
    </Prop> 
</Properties> 

Weitere Informationen über die XPath-Syntax, die XPath Syntax Seite im W3Schools Xpath Tutorial zum Beispiel sehen.

Um mit XPath loszulegen, kann es auch sehr hilfreich sein, mit Ihrem Dokument in einem der vielen XPath testers herumzuspielen.

+0

Das wird mich definitiv dorthin bringen, wo wir sein müssen. – NLMDEJ