在解析之前使用 lxml 注册命名空间

Ale*_*pin 3 python xml lxml xml-namespaces

我使用 lxml 从具有命名空间的外部服务解析 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
Run Code Online (Sandbox Code Playgroud)

我缺少什么?奇怪的是,查看 lxml 源代码来尝试理解我可能做错了什么,似乎xsi命名空间应该已经作为默认命名空间之一存在。

mzj*_*zjn 8

当解析 XML 文档并再次保存时,lxml 不会更改任何前缀(并且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())
Run Code Online (Sandbox Code Playgroud)

输出:

<ns0:Foo xmlns:ns0="http://example.com"/>
Run Code Online (Sandbox Code Playgroud)

示例 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())
Run Code Online (Sandbox Code Playgroud)

输出:

<abc:Foo xmlns:abc="http://example.com"/>
Run Code Online (Sandbox Code Playgroud)

示例 3(不带register_namespace,但具有与常规前缀关联的“众所周知”命名空间):

from lxml import etree

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

输出:

<xsi:Foo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
Run Code Online (Sandbox Code Playgroud)