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

时间:2011-02-03 12:33:05

标签: python xml namespaces elementtree

我想检索旧版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>,而在开头没有命名空间。

如何解决这些问题?

2 个答案:

答案 0 :(得分:6)

查看lxml tutorial section on namespaces。这也是article about namespaces in ElementTree

问题1:忍受它,就像其他人一样。而不是"%(ns)Event" % {'ns':NS }尝试NS+"Event"

问题2:默认情况下,只有在需要时才会写入XML声明。您可以在xml_declaration=True来电中使用write()强制它(仅限lxml)。

问题3:nsmap arg似乎只是lxml。 AFAICT需要MAPping,而不是字符串。试试nsmap={None: NS}。 effbot文章有一节描述了解决方法。

答案 1 :(得分:1)

按顺序回答您的问题:

  • 你不能只是忽略命名空间,而不是.findall()使用的路径语法,而不是“真正的”xpath(由lxml支持):你仍然被迫使用前缀,仍然需要提供一些前缀到uri的映射。

  • 使用xml_declaration=True以及encoding='utf-8'进行.write()调用(在lxml中可用,但在stdlib xml.etree中仅限于python 2.7我相信)

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