2013-04-12 7 views
5

Ich versuche, eine kompakte Darstellung von Namespaces in ElementTree oder Lxml, wenn die Unterelemente in einem anderen Namespace als das übergeordnete Element sind. Hier ist das grundlegende Beispiel:Kompakter ElementTree oder Lxml Namespaces

from lxml import etree 

country = etree.Element("country") 

name = etree.SubElement(country, "{urn:test}name") 
name.text = "Canada" 
population = etree.SubElement(country, "{urn:test}population") 
population.text = "34M" 
etree.register_namespace('tst', 'urn:test') 

print(etree.tostring(country, pretty_print=True)) 

Ich habe auch versucht, diesen Ansatz:

ns = {"test" : "urn:test"} 

country = etree.Element("country", nsmap=ns) 

name = etree.SubElement(country, "{test}name") 
name.text = "Canada" 
population = etree.SubElement(country, "{test}population") 
population.text = "34M" 

print(etree.tostring(country, pretty_print=True)) 

In beiden Fällen bekomme ich so etwas wie diese aus:

<country> 
    <ns0:name xmlns:ns0="urn:test">Canada</ns0:name> 
    <ns1:population xmlns:ns1="urn:test">34M</ns1:population> 
</country> 

Während das ist richtig, ich möchte, dass es weniger ausführlich ist - das kann ein echtes Problem bei großen Datensätzen werden (und insbesondere, weil ich ein viel größeres NS als 'urn: test' verwende).

Wenn ich bin OK mit ‚Land‘ ist in dem „urn: test“ Namespace und erklärt es wie so (im ersten Beispiel oben):

country = etree.Element("{test}country") 

dann bekomme ich folgende Ausgabe:

<ns0:country xmlns:ns0="urn:test"> 
    <ns0:name>Canada</ns0:name> 
    <ns0:population>34M</ns0:population> 
</ns0:country> 

Aber was ich will, ist wirklich so:

<country xmlns:ns0="urn:test"> 
    <ns0:name>Canada</ns0:name> 
    <ns0:population>34M</ns0:population> 
<country> 

Irgendwelche Ideen?

Antwort

1
from xml.etree import cElementTree as ET 
##ET.register_namespace('tst', 'urn:test') 
country = ET.Element("country") 
name = ET.SubElement(country, "{urn:test}name") 
name.text = "Canada" 
population = ET.SubElement(country, "{urn:test}population") 
population.text = "34M" 
print prettify(country) 

oben geben (ohne Namespace-Registrierung):

<?xml version="1.0" ?> 
<country xmlns:ns0="urn:test"> 
    <ns0:name>Canada</ns0:name> 
    <ns0:population>34M</ns0:population> 
</country> 

Und wenn ich den kommentierten Teil ::

<?xml version="1.0" ?> 
<country xmlns:tst="urn:test"> 
    <tst:name>Canada</tst:name> 
    <tst:population>34M</tst:population> 
</country> 

Note geben wird es entfernt haben: prettify Funktion ist here

+0

Danke! Das hat für mich funktioniert. –

1

Dieser Code:

from lxml import etree 

ns = {"ns0" : "urn:test"} 
country = etree.Element("country", nsmap=ns) 

name = etree.SubElement(country, "{urn:test}name") 
name.text = "Canada" 

population = etree.SubElement(country, "{urn:test}population") 
population.text = "34M" 

print(etree.tostring(country, pretty_print=True)) 

scheint die erforderliche Leistung zur Verfügung zu stellen:

<country xmlns:ns0="urn:test"> 
    <ns0:name>Canada</ns0:name> 
    <ns0:population>34M</ns0:population> 
</country> 

aber Sie müssen noch die nsmap selbst zu halten.

2
  1. der vollständige Name eines Elements enthält von {namespace-url}elementName, nicht {prefix}elementName

    >>> from lxml import etree as ET 
    >>> r = ET.Element('root', nsmap={'tst': 'urn:test'}) 
    >>> ET.SubElement(r, "{urn:test}child") 
    <Element {urn:test}child at 0x2592a80> 
    >>> ET.tostring(r) 
    '<root xmlns:tst="urn:test"><tst:child/></root>' 
    
  2. In Ihrem Fall noch kompaktere Darstellung könnte sein, wenn Sie den Standard-Namespace aktualisieren. Leider, scheint lxml nicht leer XML-Namespace zu ermöglichen, aber Sie sagen, Sie den übergeordneten Tag in den gleichen Namensraum wie Kind-Elemente setzen können, so können Sie den dafault Namespace, dass die untergeordneten Elemente gesetzt:

    >>> r = ET.Element('{urn:test}root', nsmap={None: 'urn:test'}) 
    >>> ET.SubElement(r, "{urn:test}child") 
    <Element {urn:test}child at 0x2592b20> 
    >>> ET.SubElement(r, "{urn:test}child") 
    <Element {urn:test}child at 0x25928f0> 
    >>> ET.tostring(r) 
    '<root xmlns="urn:test"><child/><child/></root>'