Python: a adição de namespaces em lxml
-
21-08-2019 - |
Pergunta
Eu estou tentando especificar um namespace usando lxml semelhante a este exemplo (retirado do aqui ):
<TreeInventory xsi:noNamespaceSchemaLocation="Trees.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
</TreeInventory>
Eu não sei como adicionar a instância de esquema de usar e também o local do esquema. A documentação me iniciou, fazendo algo como:
>>> NS = 'http://www.w3.org/2001/XMLSchema-instance'
>>> TREE = '{%s}' % NS
>>> NSMAP = {None: NS}
>>> tree = etree.Element(TREE + 'TreeInventory', nsmap=NSMAP)
>>> etree.tostring(tree, pretty_print=True)
'<TreeInventory xmlns="http://www.w3.org/2001/XMLSchema-instance"/>\n'
Eu não tenho certeza de como especificar uma instância, porém, e em seguida, também especificar uma localização. Parece que isso pode ser feito com o nsmap
chave-arg em etree.Element
, mas eu não vejo como.
Solução
Em mais alguns passos, para maior clareza:
>>> NS = 'http://www.w3.org/2001/XMLSchema-instance'
Tanto quanto eu posso ver, é o noNameSpaceSchemaLocation
atributo que você deseja namespaced, não o elemento TreeInventory
. Assim:
>>> location_attribute = '{%s}noNameSpaceSchemaLocation' % NS
>>> elem = etree.Element('TreeInventory', attrib={location_attribute: 'Trees.xsd'})
>>> etree.tostring(elem, pretty_print=True)
'<TreeInventory xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Trees.xsd"/>\n'
Este parece ser o que você queria ... Você poderia naturalmente também criar o primeiro elemento, sem atributos, e, em seguida, definir o atributo, como este:
>>> elem = etree.Element('TreeInventory')
>>> elem.set(location_attribute, 'Trees.xsd')
Como para o parâmetro nsmap
: Eu acredito que ele só é usado para definir quais prefixos para usar em serialização. Neste caso, não é necessário, porque lxml sabe o prefixo comumente usado para o namespace em questão é "xsi". Se não fosse algum espaço de nomes bem conhecido, você provavelmente veria prefixos como "ns0", "ns1" etc ..., a menos que especificado que prefixar você preferido. (Lembre-se: o prefixo não é suposto que o assunto)