Python,XML和多个“分层”默认命名空间

时间:2014-01-31 06:36:26

标签: python xml lxml xml-namespaces elementtree

我正在尝试使用Python和&处理XML文件。 xml.etree.ElementTree,并且有多个“分层”默认命名空间的问题。我需要做的是更改某些节点的文本字段的内容,然后以相同的格式保存文件。

也许一个示例文件有助于说清楚......

这就是我的代码:

from xml.etree import ElementTree

ElementTree.register_namespace('pplv', 'whatever')
ElementTree.register_namespace('', 'blah') # Register the default namespace
parse_tree = ElementTree.parse(infile)

for node in parse_tree.iter():
    if node.tag == '...':
        node.text = '...'
    if ...

    parse_tree.write(outfile)

这是我的源文件的样子

<?xml version="1.0" encoding="UTF-8"?>
<pplv:PPLVDocument xmlns:pplv="whatever">
  <pplv:node1>...</pplv:node1>
  <pplv:node2>...</pplv:node2>
  <pplv:node3 xmlns="blah">
    <node1>...</node1>
    <node2>...</node2>
  </pplv:node3>
  <pplv:node4 xmlns="blah2">
    <node1>...</node1>
    <node2>...</node2>
  </pplv:node4>
  <pplv:node5 xmlns="blah3">
    <node1>...</node1>
    <node2>...</node2>
  </pplv:node5>
</pplv:PPLVDocument>

当我使用ElementTree解析它时,注册名称空间,我得到:

<?xml version="1.0" encoding="UTF-8"?>
<pplv:PPLVDocument xmlns:pplv="whatever" xmlns="blah" xmlns:ns0="blah2" xmlns:ns1="blah3">
  <pplv:node1>...</pplv:node1>
  <pplv:node2>...</pplv:node2>
  <pplv:node3>
    <node1>...</node1>
    <node2>...</node2>
  </pplv:node3>
  <pplv:node4>
    <ns0:node1>...</ns0:node1>
    <ns0:node2>...</ns0:node2>
  </pplv:node4>
  <pplv:node5>
    <ns1:node1>...</ns1:node1>
    <ns1:node2>...</ns1:node2>
  </pplv:node5>
</pplv:PPLVDocument>

如您所见,所有名称空间定义都已“卷起”为单个节点。在我的原始文档中,默认命名空间不断重新定义(“blah”,“blah1”,“blah2”)。虽然我可以定义一个默认命名空间(“blah”),但在这种情况下,源文档中的不同点定义了多个默认命名空间; ElementTree似乎没有办法让我将更改的文件保存在这个“形状”中。

正如您可能猜到的那样,使用这些文件的(现成的)代码将不接受我正在创建的文件,但是可以正常使用原始文件结构。

很高兴切换到lxml,如果这会给我一个解决方法的方法;我只是需要修复!

提前致谢

1 个答案:

答案 0 :(得分:2)

使用lxml:

>>> parser = etree.XMLParser(remove_blank_text=True)
>>> root = etree.parse('in.xml', parser)
>>> root.xpath('//pplv:node2/text()', namespaces={'pplv': 'whatever'})
['...']
>>> root.write('out.xml', pretty_print=True)

$ cat out.xml 
<pplv:PPLVDocument xmlns:pplv="whatever">
  <pplv:node1>...</pplv:node1>
  <pplv:node2>...</pplv:node2>
  <pplv:node3 xmlns="blah">
    <node1>...</node1>
    <node2>...</node2>
  </pplv:node3>
  <pplv:node4 xmlns="blah2">
    <node1>...</node1>
    <node2>...</node2>
  </pplv:node4>
  <pplv:node5 xmlns="blah3">
    <node1>...</node1>
    <node2>...</node2>
  </pplv:node5>
</pplv:PPLVDocument>