1

I am new to Python. Now I have to replace a number of values in an XML file with Python. The example snippet of XML is:

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

What I want to do is to replace those decimal values, i.e. 112.907, with a specified value.

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

I tried with a few methods but none of them worked with my assumption that the difficulty is with the namespace prefix gmd and gco.

Please help me out. Thanks in advance!

Cheers, Alex

1
  • 1
    Which XML parser are you using? Commented Nov 23, 2011 at 1:07

1 Answer 1

3

I couldn't get lxml to process your xml without adding fake namespace declarations at the top so here is how your input looked

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

I assumed you have two lists one for the current values and one for the new ones like this

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

Here is the full code

#!/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()

and here is how the output looked like

<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>
Sign up to request clarification or add additional context in comments.

1 Comment

+1, because it made it even possible to attempt a VBScript (?horror?) solution here stackoverflow.com/a/15396987/603855.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.