2013-04-12 8 views
5

Sto cercando di ottenere una rappresentazione compatta di spazi dei nomi in ElementTree o in lxml quando i sotto elementi si trovano in uno spazio dei nomi diverso come genitore. Ecco l'esempio di base:Noci più compatte ElementTree o 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)) 

Inoltre ho provato questo approccio:

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 entrambi i casi, ottengo qualcosa di simile a questo:

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

Mentre questo è corretto, io vorrebbe che fosse meno dettagliato - questo può diventare un problema reale con set di dati di grandi dimensioni (e soprattutto perché sto usando un NS molto più grande di "urna: test").

Se io sono OK con 'paese' essere dentro il "urn: test" spazio dei nomi e dichiararlo in questo modo (nel primo esempio sopra):

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

allora ottengo il seguente output:

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

Ma quello che voglio veramente è questo:

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

Tutte le idee?

risposta

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) 

sopra darà (senza registrarti alcun namespace):

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

E, quando ho rimosso la parte commentato vi darà ::

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

nota: prettify funzione è here

+0

Grazie! Questo ha funzionato per me. –

1

Questo codice:

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

sembra fornire l'output richiesto:

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

ma è comunque necessario per mantenere l'nsmap da soli.

2
  1. il nome completo di un elemento contiene di {namespace-url}elementName, non {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. Nel tuo caso, ancora più compatto rappresentazione potrebbe essere se si aggiorna lo spazio dei nomi di default. Purtroppo, lxml non sembra consentire namespace XML vuoto, ma si dicono, si può mettere il tag genitore nello stesso spazio dei nomi di elementi figlio, in modo da poter impostare lo spazio dei nomi dafault a quella degli elementi figlio:

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