2013-04-12 8 views
5

Próbuję uzyskać zwartą reprezentację przestrzeni nazw w ElementTree lub LXML, gdy elementy podrzędne są w innej przestrzeni nazw jako obiekt nadrzędny. Oto prosty przykład:Bardziej zwarte przestrzenie nazw ElementTree lub lxml

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)) 

Próbowałem też to podejście:

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)) 

w obu przypadkach, że coś takiego się:

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

Mimo, że jest poprawny, I chciałbym, żeby było mniej gadatliwe - może to stanowić poważny problem z dużymi zbiorami danych (zwłaszcza, że ​​używam znacznie większego NS niż "urn: test").

Jeśli jestem OK z „kraju” bycia wewnątrz „urn: Test” nazw i zadeklarować je jak tak (w pierwszym przykładzie powyżej):

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

następnie pojawia się następujący komunikat:

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

Ale to, co naprawdę chcę to:

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

Jakieś pomysły?

Odpowiedz

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) 

powyżej da (bez rejestrowania nazw):

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

, a kiedy usunięto skomentował część będzie przypisywał ::

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

Uwaga: Funkcja ta jest prettifyhere

+0

Dzięki! To działało dla mnie. –

1

ten kod:

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)) 

wydaje się zapewniać wymaganą moc:

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

ale trzeba jeszcze utrzymać nsmap siebie.

2
  1. pełna nazwa elementu zawiera od {namespace-url}elementName nie {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. W twoim przypadku, nawet bardziej zwarta reprezentacja może być, jeśli zaktualizować domyślnej przestrzeni nazw. Niestety, lxml nie wydaje się, aby umożliwić pustej przestrzeni nazw XML, ale można powiedzieć, można umieścić tag nadrzędny w tej samej przestrzeni nazw jako elementów podrzędnych, dzięki czemu można ustawić nazw Dafault do elementów podrzędnych:

    >>> 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>'