2011-02-03 56 views
4

我想检索一个遗留的xml文件,操作并保存它。Python:XML中的命名空间ElementTree(或lxml)

这里是我的代码:

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") 

文件I负载包括:

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

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

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

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

问题3:nsmap arg似乎仅为lxml-only。 AFAICT它需要一个MAPPING,而不是一个字符串。尝试nsmap={None: NS}。该effbot文章有一节描述了解决这个问题的方法。

1

回答您的问题依次是:

  • 你不能忽略的命名空间,而不是在路径语法.findall()用途,而不是在“真实”的XPath(按LXML支持)之一:那里你仍然被迫使用前缀,并且仍然需要提供一些前缀到URI的映射。

  • 使用xml_declaration=True以及encoding='utf-8'.write()调用(在LXML可用,但只因为Python 2.7,我相信STDLIB xml.etree)

  • 相信LXML会做的行为像你想

相关问题