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

10

我想获取一个旧的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的lxml库,可以尝试使用XSLT。例如,可以参考以下链接中的方法:使用xmlstarlet从XML中删除所有命名空间属性 - milahu
这些问题该如何解决呢?不要使用Python的lxml库,可以尝试使用XSLT。例如,可以参考以下链接中的方法来移除XML中的所有命名空间属性:Remove all namespace attributes from xml using xmlstarlet - undefined
2个回答

10
请查看lxml教程中关于命名空间的部分。还有这篇关于ElementTree中命名空间的文章
问题1:像其他人一样忍受它。尝试使用NS+"Event"代替"%(ns)Event" % {'ns':NS }
问题2:默认情况下,只有在需要时才会写入XML声明。您可以使用write()调用中的xml_declaration=True强制写入(lxml only)。
问题3:nsmap参数似乎仅适用于lxml。AFAICT它需要一个映射而不是一个字符串。尝试使用nsmap={None: NS}。effbot文章中有一个描述此问题的解决方法的部分。

1

按顺序回答您的问题:

  • 在使用.findall()的路径语法中,您不能忽略命名空间,但在“真正”的xpath(由lxml支持)中也是如此:您仍然需要使用前缀,并且仍然需要提供一些前缀到URI映射。

  • .write()调用中使用xml_declaration=True以及encoding='utf-8'(在lxml中可用,在Python 2.7之后的stdlib xml.etree中也可用)

  • 我相信lxml会像您想要的那样运行


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接