Python:xml ElementTree(或 lxml)中的命名空间

问题描述 投票:0回答:2

我想检索旧版 xml 文件,对其进行操作并保存。

这是我的代码:

from xml.etree import cElementTree as ET
NS = "{http://www.somedomain.com/XI/Traffic/10}"

def fix_xml(filename):
    f = ET.parse(filename)
    root = f.getroot()
    eventlist = root.findall("%(ns)Event" % {'ns':NS })
    xpath = "%(ns)sEventDetail/%(ns)sEventDescription" % {'ns':NS }
    for event in eventlist:
        desc = event.find(xpath)
        desc.text = desc.text.upper() # do some editting to the text.

    ET.ElementTree(root, nsmap=NS).write("out.xml", encoding="utf-8")


shorten_xml("test.xml")

我加载的文件包含:

xmlns="http://www.somedomain.com/XI/Traffic/10"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.somedomain.com/XI/Traffic/10 10.xds"

在根标签。

我有以下与命名空间相关的问题:

  • 如您所见,对于每个标签调用,我在开始时给出了名称空间以检索子项。
  • 生成的 xml 文件开头没有
    <?xml version="1.0" encoding="utf-8"?>
  • 输出处的标签包含这样的
    <ns0:eventDescription>
    ,而我需要输出为原始
    <eventDescription>
    ,开头没有命名空间。

如何解决这些问题?

python xml namespaces elementtree
2个回答
10
投票

查看lxml 教程中关于命名空间的部分。还有这篇关于 ElementTree 中的命名空间的文章

问题 1:像其他人一样忍受它。而不是

"%(ns)Event" % {'ns':NS }
尝试
NS+"Event"

问题2:默认情况下,只有需要时才写入XML声明。您可以通过在

xml_declaration=True
调用中使用
write()
来强制它(仅限 lxml)。

问题 3:

nsmap
arg 似乎仅限于 lxml。 AFAICT 它需要一个映射,而不是一个字符串。尝试
nsmap={None: NS}
。 effbot 文章中有一节描述了此问题的解决方法。


1
投票

按顺序回答您的问题:

  • 你不能仅仅忽略命名空间,不能在

    .findall()
    使用的路径语法中忽略,但也不能在“真正的”xpath(由lxml支持)中忽略:在那里你仍然被迫使用前缀,并且仍然需要提供一些前缀到 uri 的映射。

  • 使用

    xml_declaration=True
    以及
    encoding='utf-8'
    .write()
    调用(在lxml中可用,但我相信自python 2.7以来仅在stdlib xml.etree中)

  • 我相信lxml会像你想要的那样表现

© www.soinside.com 2019 - 2024. All rights reserved.