Регистрация пространств имен с l xml перед анализом - PullRequest
1 голос
/ 22 января 2020

Я использую l xml для разбора XML из внешней службы, которая имеет пространства имен, но не регистрирует их с xmlns. Я пытаюсь зарегистрировать его вручную с помощью register_namespace, но, похоже, это не сработает.

from lxml import etree

xml = """
    <Foo xsi:type="xsd:string">bar</Foo>
"""

etree.register_namespace('xsi', 'http://www.w3.org/2001/XMLSchema-instance')
el = etree.fromstring(xml) # lxml.etree.XMLSyntaxError: Namespace prefix xsi for type on Foo is not defined

Что мне не хватает? Как ни странно, глядя на исходный код l xml, чтобы попытаться понять, что я могу делать неправильно, кажется, что пространство имен xsi должно уже быть одним из пространств имен по умолчанию.

Ответы [ 2 ]

2 голосов
/ 22 января 2020

Когда документ XML анализируется и затем сохраняется снова, l xml не меняет префиксы (и register_namespace не имеет никакого эффекта).

Если ваш XML документ не объявляется его префиксы пространства имен, это не правильно сформированное пространство имен . Использование register_namespace перед синтаксическим анализом не может исправить это.


register_namespace определяет префиксы, которые будут использоваться при сериализации вновь созданного XML документа.

Пример 1 (без register_namespace):

from lxml import etree

el = etree.Element('{http://example.com}Foo')
print(etree.tostring(el).decode())

Вывод:

<ns0:Foo xmlns:ns0="http://example.com"/>

Пример 2 (с register_namespace):

from lxml import etree

etree.register_namespace("abc", "http://example.com")

el = etree.Element('{http://example.com}Foo')
print(etree.tostring(el).decode())

Вывод:

<abc:Foo xmlns:abc="http://example.com"/>

Пример 3 (без register_namespace, но с "известным" пространством имен, связанным с обычным префиксом):

from lxml import etree

el = etree.Element('{http://www.w3.org/2001/XMLSchema-instance}Foo')
print(etree.tostring(el).decode())

Вывод:

<xsi:Foo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
2 голосов
/ 22 января 2020

Правильно сформированное пространство имен XML, которое использует пользовательские пространства имен, также должны включать само объявление пространства имен. Достаточно добавить xmlns в первый элемент:

from lxml import etree

xml = """
    <Foo xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:type='xsd:string'>bar</Foo>
"""
el = etree.fromstring(xml)    
print (el)

Итак, технически, если ваш XML использует xsi, но не содержит декларации пространства имен, это не очень хорошо (пространство имен) Formed XML.

См. также Как ограничить значение элемента XML с помощью xsi: type в XSD?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...