8

我想检索一个遗留的 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>的,开始时没有命名空间。

这些如何解决?

4

2 回答 2

8

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

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

问题 2:默认情况下,仅在需要时才编写 XML 声明。您可以通过xml_declaration=Truewrite()通话中使用来强制它(仅限 lxml)。

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

于 2011-02-03T13:37:07.090 回答
1

按顺序回答您的问题:

  • 您不能只忽略名称空间,而不是在.findall()使用的路径语法中,但也不能在“真实”xpath(由lxml支持)中:在那里您仍然被迫使用前缀,并且仍然需要提供一些前缀-to-uri 映射。

  • xml_declaration=True与调用encoding='utf-8'一起使用(.write()在 lxml 中可用,但在 stdlib xml.etree 中仅从 python 2.7 开始我相信)

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

于 2011-02-03T13:37:07.810 回答