如何用Python替换XML中的节点值

时间:2011-11-23 01:05:00

标签: python xml namespaces elementtree

我是Python新手。现在我必须用Python替换XML文件中的许多值。 XML的示例片段是:

<gmd:extent>
    <gmd:EX_Extent>
      <gmd:description gco:nilReason="missing">
        <gco:CharacterString />
      </gmd:description>
      <gmd:geographicElement>
        <gmd:EX_GeographicBoundingBox>
          <gmd:westBoundLongitude>
            <gco:Decimal>112.907</gco:Decimal>
          </gmd:westBoundLongitude>
          <gmd:eastBoundLongitude>
            <gco:Decimal>158.96</gco:Decimal>
          </gmd:eastBoundLongitude>
          <gmd:southBoundLatitude>
            <gco:Decimal>-54.7539</gco:Decimal>
          </gmd:southBoundLatitude>
          <gmd:northBoundLatitude>
            <gco:Decimal>-10.1357</gco:Decimal>
          </gmd:northBoundLatitude>
        </gmd:EX_GeographicBoundingBox>
      </gmd:geographicElement>
    </gmd:EX_Extent>
  </gmd:extent>

我想要做的是用指定的值替换那些十进制值,即112.907。

<gmd:extent>
    <gmd:EX_Extent>
      <gmd:description gco:nilReason="missing">
        <gco:CharacterString />
      </gmd:description>
      <gmd:geographicElement>
        <gmd:EX_GeographicBoundingBox>
          <gmd:westBoundLongitude>
            <gco:Decimal>new value</gco:Decimal>
          </gmd:westBoundLongitude>
          <gmd:eastBoundLongitude>
            <gco:Decimal>new value</gco:Decimal>
          </gmd:eastBoundLongitude>
          <gmd:southBoundLatitude>
            <gco:Decimal>new value</gco:Decimal>
          </gmd:southBoundLatitude>
          <gmd:northBoundLatitude>
            <gco:Decimal>new value</gco:Decimal>
          </gmd:northBoundLatitude>
        </gmd:EX_GeographicBoundingBox>
      </gmd:geographicElement>
    </gmd:EX_Extent>
  </gmd:extent>

我尝试了几种方法,但是没有一种方法可以解释我的假设,即命名空间前缀gmd和gco存在困难。

请帮帮我。提前谢谢!

干杯,亚历克斯

1 个答案:

答案 0 :(得分:3)

我无法让lxml处理你的xml而不在顶部添加虚假的命名空间声明,所以这是输入的显示方式

<gmd:extent xmlns:gmd="urn:x:y:z:1" xmlns:gco="urn:x:y:z:1">
    <gmd:EX_Extent>
        <gmd:description gco:nilReason="missing">
            <gco:CharacterString />
        </gmd:description>
        <gmd:geographicElement>
            <gmd:EX_GeographicBoundingBox>
                <gmd:westBoundLongitude>
                    <gco:Decimal>112.907</gco:Decimal>
                </gmd:westBoundLongitude>
                <gmd:eastBoundLongitude>
                    <gco:Decimal>158.96</gco:Decimal>
                </gmd:eastBoundLongitude>
                <gmd:southBoundLatitude>
                    <gco:Decimal>-54.7539</gco:Decimal>
                </gmd:southBoundLatitude>
                <gmd:northBoundLatitude>
                    <gco:Decimal>-10.1357</gco:Decimal>
                </gmd:northBoundLatitude>
            </gmd:EX_GeographicBoundingBox>
        </gmd:geographicElement>
    </gmd:EX_Extent>
</gmd:extent>

我假设您有两个列表用于当前值,一个用于新列表,如此

old = [112.907,158.96,-54.7539,-10.1357] 新= [1,2,3,4] d = dict(zip(旧,新))

这是完整的代码

#!/usr/bin/env python
import sys
from lxml import etree

def process(fname):
    f = open(fname)
    tree = etree.parse(f)
    root = tree.getroot()
    old = [112.907, 158.96, -54.7539, -10.1357]
    new = [1,2,3,4]
    d = dict(zip(old,new))
    nodes = root.findall('.//gco:Decimal', root.nsmap)
    for node in nodes:
        node.text = str(d[float(node.text)])
    f.close()
    return etree.tostring(root, pretty_print=True)

def main():
    fname = sys.argv[1]
    text = process(fname)
    outfile = open('out.xml', 'w+')
    outfile.write(text)
    outfile.close()

if __name__ == '__main__':
    main()

以下是输出的结果

<gmd:extent xmlns:gmd="urn:x:y:z:1" xmlns:gco="urn:x:y:z:1">
    <gmd:EX_Extent>
        <gmd:description gco:nilReason="missing">
            <gco:CharacterString/>
        </gmd:description>
        <gmd:geographicElement>
            <gmd:EX_GeographicBoundingBox>
                <gmd:westBoundLongitude>
                    <gco:Decimal>1</gco:Decimal>
                </gmd:westBoundLongitude>
                <gmd:eastBoundLongitude>
                    <gco:Decimal>2</gco:Decimal>
                </gmd:eastBoundLongitude>
                <gmd:southBoundLatitude>
                    <gco:Decimal>3</gco:Decimal>
                </gmd:southBoundLatitude>
                <gmd:northBoundLatitude>
                    <gco:Decimal>4</gco:Decimal>
                </gmd:northBoundLatitude>
            </gmd:EX_GeographicBoundingBox>
        </gmd:geographicElement>
    </gmd:EX_Extent>
</gmd:extent>