在 Python 中使用 ElementTree 解析带有命名空间的 XML
Parsing XML with namespaces using ElementTree in Python
我有一个 xml,它的一小部分如下所示:
<?xml version="1.0" ?>
<i:insert xmlns:i="urn:com:xml:insert" xmlns="urn:com:xml:data">
<data>
<image imageId="1"></image>
<content>Content</content>
</data>
</i:insert>
当我使用 ElementTree
解析它并将其保存到文件时,我看到以下内容:
<ns0:insert xmlns:ns0="urn:com:xml:insert" xmlns:ns1="urn:com:xml:data">
<ns1:data>
<ns1:image imageId="1"></ns1:image>
<ns1:content>Content</ns1:content>
</ns1:data>
</ns0:insert>
为什么它会更改前缀并将它们放在各处?使用 minidom
我没有这样的问题。它配置了吗? ElementTree
的文档很差。
问题是,在这样的解析之后我找不到任何节点,例如 image
- 如果我像 {namespace}image
或只是 image
一样使用它,无论有没有命名空间都找不到它.为什么?非常感谢任何建议。
我已经尝试过的:
import xml.etree.ElementTree as ET
tree = ET.parse('test.xml')
root = tree.getroot()
for a in root.findall('ns1:image'):
print a.attrib
这个 returns 一个错误,另一个 returns 没有:
for a in root.findall('{urn:com:xml:data}image'):
print a.attrib
我也试过这样创建命名空间并使用它:
namespaces = {'ns1': 'urn:com:xml:data'}
for a in root.findall('ns1:image', namespaces):
print a.attrib
它returns没什么。我做错了什么?
据我了解,这与ET中的命名空间识别有关。
从这里开始http://effbot.org/zone/element-namespaces.htm
When you save an Element tree to XML, the standard Element serializer generates unique prefixes for all URI:s that appear in the tree. The prefixes usually have the form “ns” followed by a number. For example, the above elements might be serialized with the prefix ns0 for “http://www.w3.org/1999/xhtml” and ns1 for “http://effbot.org/namespace/letters”.
如果要使用特定前缀,可以将 prefix/uri 映射添加到 ElementTree 模块中的全局 table。在 1.3 及更高版本中,您可以通过调用 register_namespace 函数来执行此操作。在早期版本中,您可以直接访问内部table:
元素树 1.3
ET.register_namespace(前缀,uri)
元素树 1.2 (Python 2.5)
ET._namespace_map[uri] = 前缀
注意参数顺序;该函数首先采用前缀,而原始字典从 URI:s 映射到前缀。
你问题中的这个片段,
for a in root.findall('{urn:com:xml:data}image'):
print a.attrib
不输出任何内容,因为它只查找树根的直接 {urn:com:xml:data}image
个子节点。
这段代码稍作修改,
for a in root.findall('.//{urn:com:xml:data}image'):
print a.attrib
将打印 {'imageId': '1'}
因为它使用 .//
,它会在所有级别上选择匹配的子元素。
参考:https://docs.python.org/2/library/xml.etree.elementtree.html#supported-xpath-syntax.
有点烦人的是,ElementTree 不仅默认保留原始命名空间前缀,但请记住,无论如何前缀都不重要。当序列化 XML 时,register_namespace()
函数可用于设置想要的前缀。该函数对解析或搜索没有任何影响。
我有一个 xml,它的一小部分如下所示:
<?xml version="1.0" ?>
<i:insert xmlns:i="urn:com:xml:insert" xmlns="urn:com:xml:data">
<data>
<image imageId="1"></image>
<content>Content</content>
</data>
</i:insert>
当我使用 ElementTree
解析它并将其保存到文件时,我看到以下内容:
<ns0:insert xmlns:ns0="urn:com:xml:insert" xmlns:ns1="urn:com:xml:data">
<ns1:data>
<ns1:image imageId="1"></ns1:image>
<ns1:content>Content</ns1:content>
</ns1:data>
</ns0:insert>
为什么它会更改前缀并将它们放在各处?使用 minidom
我没有这样的问题。它配置了吗? ElementTree
的文档很差。
问题是,在这样的解析之后我找不到任何节点,例如 image
- 如果我像 {namespace}image
或只是 image
一样使用它,无论有没有命名空间都找不到它.为什么?非常感谢任何建议。
我已经尝试过的:
import xml.etree.ElementTree as ET
tree = ET.parse('test.xml')
root = tree.getroot()
for a in root.findall('ns1:image'):
print a.attrib
这个 returns 一个错误,另一个 returns 没有:
for a in root.findall('{urn:com:xml:data}image'):
print a.attrib
我也试过这样创建命名空间并使用它:
namespaces = {'ns1': 'urn:com:xml:data'}
for a in root.findall('ns1:image', namespaces):
print a.attrib
它returns没什么。我做错了什么?
据我了解,这与ET中的命名空间识别有关。
从这里开始http://effbot.org/zone/element-namespaces.htm
When you save an Element tree to XML, the standard Element serializer generates unique prefixes for all URI:s that appear in the tree. The prefixes usually have the form “ns” followed by a number. For example, the above elements might be serialized with the prefix ns0 for “http://www.w3.org/1999/xhtml” and ns1 for “http://effbot.org/namespace/letters”.
如果要使用特定前缀,可以将 prefix/uri 映射添加到 ElementTree 模块中的全局 table。在 1.3 及更高版本中,您可以通过调用 register_namespace 函数来执行此操作。在早期版本中,您可以直接访问内部table:
元素树 1.3
ET.register_namespace(前缀,uri)
元素树 1.2 (Python 2.5)
ET._namespace_map[uri] = 前缀
注意参数顺序;该函数首先采用前缀,而原始字典从 URI:s 映射到前缀。
你问题中的这个片段,
for a in root.findall('{urn:com:xml:data}image'):
print a.attrib
不输出任何内容,因为它只查找树根的直接 {urn:com:xml:data}image
个子节点。
这段代码稍作修改,
for a in root.findall('.//{urn:com:xml:data}image'):
print a.attrib
将打印 {'imageId': '1'}
因为它使用 .//
,它会在所有级别上选择匹配的子元素。
参考:https://docs.python.org/2/library/xml.etree.elementtree.html#supported-xpath-syntax.
有点烦人的是,ElementTree 不仅默认保留原始命名空间前缀,但请记住,无论如何前缀都不重要。当序列化 XML 时,register_namespace()
函数可用于设置想要的前缀。该函数对解析或搜索没有任何影响。