Search code examples
bashmacossedkmlxmlstarlet

bash, xmlstarlet to extract two nodes


So, I'm trying to extract some geo data from a KML file. Everything that I see suggests that I could use xmlstarlet in bash. I'm trying to get a CSV file from this (representative) part of sample data (modified earlier to be single line):

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2" 
     xmlns:gx="http://www.google.com/kml/ext/2.2">
  <Document>
    <Placemark>
      <open>1</open>
      <gx:Track>
        <altitudeMode>clampToGround</altitudeMode>
        <when>2015-12-24T18:20:57Z</when>
        <gx:coord>-87.2788204 36.5984675 0</gx:coord>
        <when>2015-12-24T18:20:42Z</when>
        <gx:coord>-87.2784049 36.597298699999996  0</gx:coord>
      </gx:Track>
    </Placemark>
  </Document>
</kml>

That reads:

2015-12-24 18:20:57 -87.2788204 36.5984675 0
2015-12-24 18:20:42 -87.2784049 36.597298699999996 0

After a little processing with sed (OSX Sierra).

Using the following, I can extract the "gx:coord" node, but the same doesn't apply to the "when" node (why?):

xmlstarlet sel -t -m '//gx:coord' -v . -n <in.kml > out.csv

After trying to piece together rudimentary solutions with multiple sed iterations, I am back to this as the solution that would work consistently, cleanly and yield the best result (xmlstarlet to yield the "when" and "gx:coord" data... I'm unfamiliar with XLST). Suggestions on the command or steps to make this happen? Thanks!


Solution

  • It's because when is in the default namespace http://www.opengis.net/kml/2.2.

    Try binding a prefix to the namespace (with -N).

    Example...

    xmlstarlet sel -N kml='http://www.opengis.net/kml/2.2' -t -m '//gx:coord' -v "concat(preceding-sibling::kml:when[1],' ',.)" -n in.kml
    

    Output...

    2015-12-24T18:20:57Z -87.2788204 36.5984675 0
    2015-12-24T18:20:42Z -87.2784049 36.597298699999996  0
    

    I just noticed that you're also trying to do some string manipulation on when. It can get ugly on the command line, so I'd prefer XSLT, but here's an option...

    xmlstarlet sel -N kml='http://www.opengis.net/kml/2.2' -t -m '//gx:coord' -v "concat(translate(preceding-sibling::kml:when[1],'TZ','  '),.)" -n in.kml
    

    Output...

    2015-12-24 18:20:57 -87.2788204 36.5984675 0
    2015-12-24 18:20:42 -87.2784049 36.597298699999996  0