Montag, 22. November 2010

GPX-Dateien nach SDO_GEOMETRY umwandeln

Jüngst habe ich für einen Kollegen einen GPS-Track in die Datenbank geladen. Ich hatte eine .gpx-Datei, die in etwa so aussieht ...
<gpx xmlns="http://www.topografix.com/GPX/1/1" tc2=" ...
   <trk>
       <name>2010-11-16T03:46:55Z</name>
       <trkseg>
           <trkpt lat="51.4799802" lon="7.9678522">
               <ele>270.7484131</ele>
               <time>2010-11-16T03:46:55Z</time>
           </trkpt>
           <trkpt lat="51.4799436" lon="7.9678679">
               <ele>264.0192871</ele>
               <time>2010-11-16T03:47:06Z</time>
           </trkpt>
           <trkpt lat="51.4797696" lon="7.9681059">
               <ele>264.4998779</ele>
               <time>2010-11-16T03:47:12Z</time>
           </trkpt>
           <trkpt lat="51.4797497" lon="7.9681919">
               <ele>264.9805908</ele>
               <time>2010-11-16T03:47:14Z</time>
           </trkpt>
Zunächst hatte ich ein wenig nach Converter-Software gegoogelt, wurde jedoch nicht so recht fündig (komische Lizenzbedingungen, keine Konvertierung nach GML oder KML, sondern nur in andere Formate). Da es aber um eine einfach zu verstehende XML-Datei geht, beschloß ich, mir einfach selbst eine Funktion zu schreiben, welche die Arbeit erledigt. Und hier ist sie ...
create or replace function convert_gpx_to_sdo(
 p_gpxfile in xmltype,
 p_lrs     in number default 0
) return sdo_geometry is
 v_ordinates sdo_ordinate_array := sdo_ordinate_array();
 v_gtype     number;

 v_cnt       pls_integer := 1;

 v_startts   timestamp;
 v_interval  interval day(9) to second;

 c_gpxns     varchar2(200) := 'xmlns="http://www.topografix.com/GPX/1/1"';
begin
 if p_lrs = 1 then
   v_gtype := 3302;
 else
   v_gtype := 2002;
 end if;

 for tp in (
   select
     extractvalue(value(tp), '/trkpt/@lon', c_gpxns) x,
     extractvalue(value(tp), '/trkpt/@lat', c_gpxns) y,
     extractvalue(value(tp), '/trkpt/time', c_gpxns) m
   from table(xmlsequence(extract(p_gpxfile, '//trkpt', c_gpxns))) tp
 ) loop
   if v_cnt = 1 then
     v_startts := to_timestamp(tp.m, 'YYYY-MM-DD"T"HH24:MI:SS"Z"');
   end if;
   if p_lrs = 1 then
     v_ordinates.extend(3);
   else
     v_ordinates.extend(2);
   end if;
   v_ordinates(v_cnt) := tp.x;
   v_cnt := v_cnt + 1;
   v_ordinates(v_cnt) := tp.y;
   v_cnt := v_cnt + 1;
   if p_lrs = 1 then
     v_interval := to_timestamp(tp.m,  'YYYY-MM-DD"T"HH24:MI:SS"Z"') - v_startts;
     v_ordinates(v_cnt) :=
      extract(MINUTE from v_interval) +
      extract(HOUR from v_interval) * 60 +
      extract(SECOND from v_interval) / 60;
     v_cnt := v_cnt + 1;
    end if;
 end loop;

 return sdo_geometry(v_gtype, 8307, null, sdo_elem_info_array(1,2,1), v_ordinates);
end convert_gpx_to_sdo;
/
sho err
Die Funktion nimmt das GPX-File (XMLTYPE) als ersten Parameter entgegen. Der zweite Parameter gibt an, ob eine Linear Referencing-Geometrie zurückgegeben werden soll. Wenn ja, werden die Measures in Minuten gespeichert. Gebt hier entweder "1" oder "0" an ... Man könnte hier sicherlich noch mehr machen: die GPX-Dateien enthalten eine Höhenangabe - man könnte also auch 3D-Geometrien bauen ...
Vielleicht jemand diese erste Version brauchen - viel Spaß damit!

Keine Kommentare:

Kommentar veröffentlichen