Frage

Ich versuche, kundenspezifische XML-Dateien aus einer Vorlage XML-Datei in Python zu generieren.

Konzeptionell, möchte ich in der Vorlage xml lesen, einige Elemente entfernen, ändern einige Textattribute, und die neue XML in eine Datei zu schreiben. Ich wollte es so etwas wie dies funktioniert:

conf_base = ConvertXmlToDict('config-template.xml')
conf_base_dict = conf_base.UnWrap()
del conf_base_dict['root-name']['level1-name']['leaf1']
del conf_base_dict['root-name']['level1-name']['leaf2']

conf_new = ConvertDictToXml(conf_base_dict)

Jetzt möchte ich eine Datei schreiben, aber ich sehe nicht, wie zu bekommen ElementTree.ElementTree.write ()

conf_new.write('config-new.xml') 

Gibt es eine Möglichkeit, dies zu tun, oder kann jemand vorschlagen, dies eine andere Art und Weise zu tun?

War es hilfreich?

Lösung

Für eine einfache Manipulation von XML in Python, wie ich die Schöne Suppe Bibliothek. Es funktioniert so etwas wie folgt aus:

Beispiel-XML-Datei:

<root>
  <level1>leaf1</level1>
  <level2>leaf2</level2>
</root>

Python-Code:

from BeautifulSoup import BeautifulStoneSoup, Tag, NavigableString

soup = BeautifulStoneSoup('config-template.xml') # get the parser for the xml file
soup.contents[0].name
# u'root'

Sie können die Knotennamen als Methoden verwenden:

soup.root.contents[0].name
# u'level1'

Es ist auch möglich, reguläre Ausdrücke zu verwenden:

import re
tags_starting_with_level = soup.findAll(re.compile('^level'))
for tag in tags_starting_with_level: print tag.name
# level1
# level2

Hinzufügen und Einfügen neuer Knoten ist ziemlich einfach:

# build and insert a new level with a new leaf
level3 = Tag(soup, 'level3')
level3.insert(0, NavigableString('leaf3')
soup.root.insert(2, level3)

print soup.prettify()
# <root>
#  <level1>
#   leaf1
#  </level1>
#  <level2>
#   leaf2
#  </level2>
#  <level3>
#   leaf3
#  </level3>
# </root>

Andere Tipps

Dieses finden Sie eine dict bekommen minus Attribute ... weiß nicht, ob dies jedem nützlich ist. Ich war selbst für eine xml zu dict Lösung suchen, wenn ich mit dieser kam.



import xml.etree.ElementTree as etree

tree = etree.parse('test.xml')
root = tree.getroot()

def xml_to_dict(el):
  d={}
  if el.text:
    d[el.tag] = el.text
  else:
    d[el.tag] = {}
  children = el.getchildren()
  if children:
    d[el.tag] = map(xml_to_dict, children)
  return d

Das http://www.w3schools.com/XML/note.xml

<note>
 <to>Tove</to>
 <from>Jani</from>
 <heading>Reminder</heading>
 <body>Don't forget me this weekend!</body>
</note>

entspräche dies:


{'note': [{'to': 'Tove'},
          {'from': 'Jani'},
          {'heading': 'Reminder'},
          {'body': "Don't forget me this weekend!"}]}

Ich bin mir nicht sicher, ob die Info-Umwandlung auf verschachtelte dicts ersten einfacher ist. Mit ElementTree, können Sie dies tun:

import xml.etree.ElementTree as ET
doc = ET.parse("template.xml")
lvl1 = doc.findall("level1-name")[0]
lvl1.remove(lvl1.find("leaf1")
lvl1.remove(lvl1.find("leaf2")
# or use del lvl1[idx]
doc.write("config-new.xml")

ElementTree wurde so konzipiert, dass Sie müssen nicht Ihre XML-Bäume auf Listen konvertieren und Attribute zuerst, da es genau die intern verwendet.

Es unterstützt auch als kleine Untergruppe von XPath .

Meine Modifikation von Daniels Antwort, ein geringfügig ordentlicheres Wörterbuch geben:

def xml_to_dictionary(element):
    l = len(namespace)
    dictionary={}
    tag = element.tag[l:]
    if element.text:
        if (element.text == ' '):
            dictionary[tag] = {}
        else:
            dictionary[tag] = element.text
    children = element.getchildren()
    if children:
        subdictionary = {}
        for child in children:
            for k,v in xml_to_dictionary(child).items():
                if k in subdictionary:
                    if ( isinstance(subdictionary[k], list)):
                        subdictionary[k].append(v)
                    else:
                        subdictionary[k] = [subdictionary[k], v]
                else:
                    subdictionary[k] = v
        if (dictionary[tag] == {}):
            dictionary[tag] = subdictionary
        else:
            dictionary[tag] = [dictionary[tag], subdictionary]
    if element.attrib:
        attribs = {}
        for k,v in element.attrib.items():
            attribs[k] = v
        if (dictionary[tag] == {}):
            dictionary[tag] = attribs
        else:
            dictionary[tag] = [dictionary[tag], attribs]
    return dictionary

Namespace ist die xmlns Zeichenfolge, einschließlich Klammern, dass ElementTree an alle Tags prepends, so hier habe ich klären, da es ein Namensraum für das gesamte Dokument ist

NB, dass ich die rohe XML zu so eingestellt, dass ‚leeren‘ Tags höchstens einem ‚‘ Text-Eigenschaft in der ElementTree Darstellung erzeugen würde

spacepattern = re.compile(r'\s+')
mydictionary = xml_to_dictionary(ElementTree.XML(spacepattern.sub(' ', content)))

würde zum Beispiel geben

{'note': {'to': 'Tove',
         'from': 'Jani',
         'heading': 'Reminder',
         'body': "Don't forget me this weekend!"}}

es für bestimmten XML ausgelegt ist, die im Grunde äquivalent zu json, sollte Element behandeln Attribute wie

<elementName attributeName='attributeContent'>elementContent</elementName>

zu

gibt es die Möglichkeit einer Verschmelzung das Attribut Wörterbuch / Subtag Wörterbuch ähnlich wie wiederholen Subtags verschmolzen werden, obwohl Verschachtelung der Listen Art angemessen erscheint: -)

Das Hinzufügen dieser Zeile

d.update(('@' + k, v) for k, v in el.attrib.iteritems())

in der user247686 Code Knoten haben auch Attribute.

es in diesem Beitrag https://stackoverflow.com/a/7684581/1395962

Beispiel:

import xml.etree.ElementTree as etree
from urllib import urlopen

xml_file = "http://your_xml_url"
tree = etree.parse(urlopen(xml_file))
root = tree.getroot()

def xml_to_dict(el):
    d={}
    if el.text:
        d[el.tag] = el.text
    else:
        d[el.tag] = {}
    children = el.getchildren()
    if children:
        d[el.tag] = map(xml_to_dict, children)

    d.update(('@' + k, v) for k, v in el.attrib.iteritems())

    return d

Anruf als

xml_to_dict(root)

Haben Sie versucht das?

print xml.etree.ElementTree.tostring( conf_new )

direkteste Weg zu mir:

root        = ET.parse(xh)
data        = root.getroot()
xdic        = {}
if data > None:
    for part in data.getchildren():
        xdic[part.tag] = part.text

XML hat eine reiche infoset, und es dauert einige spezielle Tricks, dass in einem Python-Wörterbuch darzustellen. Elemente sind in der Reihenfolge, sind Attribute unterscheiden von Elementkörper, etc.

Ein Projekt Umläufe zwischen XML und Python Wörterbücher, mit einigen Konfigurationsoptionen zu handhaben die Vor- und Nachteile auf unterschiedliche Weise zu handhaben ist XML-Unterstützung in Abbeizen Werkzeuge . Version 1.3 und höher erforderlich. Es ist nicht reines Python (und in der Tat wird entwickelt, um C ++ / Python Interaktion einfacher zu machen), aber es könnte für verschiedene Anwendungsfälle geeignet sein.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top