python - ElementTree 是否会生成自己的 nsmap 而 lxml.etree 不会?
问题描述
该线程解释了nsmap
in 的性质lxml.etree
。鉴于以下 XML 和解析代码,我尝试ElementTree.dump
查看etree.dump
。来自 ET 的显示显示了各种命名空间ns1
,ns2
等等。这是否意味着 ET 实际上生成了内部命名空间?如果是这样,我们是否可以或如何使用它,例如,搜索我们知道其名称但不知道其 URI 的元素?
my_xml.xml
<?xml version="1.0" encoding="UTF-8"?>
<data>
<country name="Liechtenstein" xmlns="aaa:bbb:ccc:liechtenstein:eee">
<rank updated="yes">2</rank>
<holidays>
<christmas>Yes</christmas>
</holidays>
<year>2008</year>
<gdppc>141100</gdppc>
<neighbor name="Austria" direction="E"/>
<neighbor name="Switzerland" direction="W"/>
</country>
<country name="Singapore" xmlns="aaa:bbb:ccc:singapore:eee">
<continent>Asia</continent>
<holidays>
<christmas>Yes</christmas>
</holidays>
<rank updated="yes">5</rank>
<year>2011</year>
<gdppc>59900</gdppc>
<neighbor name="Malaysia" direction="N"/>
</country>
<country name="Panama" xmlns="aaa:bbb:ccc:panama:eee">
<rank updated="yes">69</rank>
<year>2011</year>
<gdppc>13600</gdppc>
<neighbor name="Costa Rica" direction="W"/>
<neighbor name="Colombia" direction="E"/>
</country>
</data>
parsing.py
import lxml.etree as etree
tree = etree.parse('my_xml.xml')
root = tree.getroot()
ET.dump
<ns0:data xmlns:ns0="aaa:bbb:ccc:ddd:eee" xmlns:ns1="aaa:bbb:ccc:liechtenstein:eee" xmlns:ns2="aaa:bbb:ccc:singapore:eee" xmlns:ns3="aaa:bbb:ccc:panama:eee">
<ns1:country name="Liechtenstein">
<ns1:rank updated="yes">2</ns1:rank>
<ns1:year>2008</ns1:year>
<ns1:gdppc>141100</ns1:gdppc>
<ns1:neighbor name="Austria" direction="E" />
<ns1:neighbor name="Switzerland" direction="W" />
</ns1:country>
<ns2:country name="Singapore">
<ns2:continent>Asia</ns2:continent>
<ns2:holidays>
<ns2:christmas>Yes</ns2:christmas>
</ns2:holidays>
<ns2:rank updated="yes">5</ns2:rank>
<ns2:year>2011</ns2:year>
<ns2:gdppc>59900</ns2:gdppc>
<ns2:neighbor name="Malaysia" direction="N" />
</ns2:country>
<ns3:country name="Panama">
<ns3:rank updated="yes">69</ns3:rank>
<ns3:year>2011</ns3:year>
<ns3:gdppc>13600</ns3:gdppc>
<ns3:neighbor name="Costa Rica" direction="W" />
<ns3:neighbor name="Colombia" direction="E" />
</ns3:country>
</ns0:data>
etree.dump
<data xmlns="aaa:bbb:ccc:ddd:eee">
<country xmlns="aaa:bbb:ccc:liechtenstein:eee" name="Liechtenstein">
<rank updated="yes">2</rank>
<year>2008</year>
<gdppc>141100</gdppc>
<neighbor name="Austria" direction="E"/>
<neighbor name="Switzerland" direction="W"/>
</country>
<country xmlns="aaa:bbb:ccc:singapore:eee" name="Singapore">
<continent>Asia</continent>
<holidays>
<christmas>Yes</christmas>
</holidays>
<rank updated="yes">5</rank>
<year>2011</year>
<gdppc>59900</gdppc>
<neighbor name="Malaysia" direction="N"/>
</country>
<country xmlns="aaa:bbb:ccc:panama:eee" name="Panama">
<rank updated="yes">69</rank>
<year>2011</year>
<gdppc>13600</gdppc>
<neighbor name="Costa Rica" direction="W"/>
<neighbor name="Colombia" direction="E"/>
</country>
</data>
解决方案
ElementTree (ET) 和 lxml 在处理命名空间的方式上有所不同
ET 通常不保留输入文档中定义的命名空间前缀,也不存储命名空间是否为默认命名空间。ET 还将所有命名空间声明移动到最外层元素。
lxml 通常保留前缀和默认命名空间。
例如,如果您的输入文档是:
<root xmlns:myprefix="https://www.myuri.com">
或者如果输入具有默认命名空间:
<root xmlns="https://www.myuri.com">
然后 lxml 将保留有关此文档的所有内容,而 ET 可以将其转换为
<root xmlns:ns0="https://www.myuri.com">
ET 的修改不会改变文档的语义,但如果您想防止这种情况发生,我认为在解析 XML 文件之前注册所有命名空间是唯一的解决方案。
ET 命名空间映射不是更好或更有用
这是否意味着 ET 实际上会生成内部命名空间?如果是这样,我们是否可以或如何使用它,例如,搜索我们知道其名称但不知道其 URI 的元素?
不,我不认为 ET 命名空间映射比从 lxml 获得的映射更有用(或更少)。在这两种情况下,基本上定义了相同的命名空间并使用了相同的映射。
正如我之前提到的,知道元素的名称而不知道其名称空间 URI 是不常见的。如果元素的命名空间 URI 是不可预测的并且是先验未知的,这是一个原因
- 更改您的 XML 格式(如果您自己负责)
- 抱怨此类文件并坚持更改(如果其他人负责)
在任何情况下,在您展示的 XML 文档中,命名空间肯定不会以预期的方式使用。不需要每个country
元素都驻留在自己的命名空间中。
推荐阅读
- php - 如何在刀片、laravel 中添加简写 if 语句?
- coldfusion - 尝试使用 ColdFusion 11 实现 SAML 2.0
- python - 根据 Pandas 中的其他信息更改数据框中列的一部分
- excel - 根据单元格值添加行
- multithreading - Spring Batch Itemreader 将相同的对象两次传递给 Itemprocessor
- javascript - 从 JSON 数组中删除字段
- android - 如何通过android studio中的多个按钮为两个textview输入文本?
- r - 在绘图标题中使用数据框变量名称
- java - 埃拉托色尼筛(使用 LINKEDLIST)
- sql - Teradata:使用通配符搜索项目的最佳方式