slightly more robust XML parsing of the GPX track (elevation is now
authorerik <erik@77661180-640e-0410-b3a8-9f9b13e6d0e0>
Sun, 20 Aug 2006 15:53:57 +0000 (15:53 +0000)
committererik <erik@77661180-640e-0410-b3a8-9f9b13e6d0e0>
Sun, 20 Aug 2006 15:53:57 +0000 (15:53 +0000)
optional).

DomUtils now uses XMLException instead of the 4 different types from
before.

crawler/basic/src/org/wamblee/crawler/Action.java
crawler/kiss/conf/kiss/programs.xml
gps/src/org/wamblee/gpx/GpxParser.java
gps/src/org/wamblee/gpx/gpx.xsd [new file with mode: 0644]
support/src/org/wamblee/xml/DomUtils.java
support/src/org/wamblee/xml/XMLException.java [new file with mode: 0644]

index f24cacd0ea4547c11a9afec2af5201d49c325e0a..cd9b4e2a74a83062757133aa697259d133522050 100644 (file)
@@ -16,7 +16,6 @@
 
 package org.wamblee.crawler;
 
-import org.apache.commons.httpclient.NameValuePair;
 import org.dom4j.Element;
 
 /**
index 38fb018d25986a892b4c22830708ace2a6eb0001..a07c4c57caea2649b680a478e90449acdf9f4bc7 100644 (file)
     <action>notify</action>
     <match field="description">sf-|(sci-fi)|(science fiction)</match>
   </program>
+
+  <program>
+    <match>invasion</match>
+  </program>
   
   <program>
     <action>notify</action>
index 500091b3bb02adf2ef4e4cdf4923c6f442715561..fe675ce670abd5092259baceba2ab79b2f26a86c 100644 (file)
 
 package org.wamblee.gpx;
 
-import java.io.IOException;
 import java.io.InputStream;
 import java.util.Iterator;
 
-import javax.xml.parsers.ParserConfigurationException;
-
 import org.dom4j.Document;
 import org.dom4j.Element;
 import org.wamblee.gps.track.Track;
 import org.wamblee.gps.track.TrackPoint;
 import org.wamblee.xml.DomUtils;
-import org.xml.sax.SAXException;
+import org.wamblee.xml.XMLException;
 
 /**
  * Parser for GPX tracks.  
  */
 public class GpxParser {
     
+    private static final String SCHEMA_RESOURCE = "gpx.xsd";
+    
     public GpxParser() { 
         // Empty.
     }
     
-    public Track parse(InputStream aIs) throws SAXException, ParserConfigurationException, IOException { 
+    public Track parse(InputStream aIs) throws XMLException { 
         Document doc = DomUtils.convert(DomUtils.read(aIs));
         return parse(doc);
     }
@@ -63,7 +62,11 @@ public class GpxParser {
         //System.out.println(trkpt.asXML() + "|\n"); 
         double latitude = new Double(trkpt.attributeValue("lat"));
         double longitude = new Double(trkpt.attributeValue("lon"));
-        double elevation = new Double(trkpt.elementText("ele"));
+        Element ele = trkpt.element("ele");
+        double elevation = 0.0;
+        if ( ele != null ) { 
+            elevation = new Double(ele.getText());
+        }
         //System.out.println("  lat = " + lat + " lon = " + lon + " ele = " + ele);
         return new TrackPoint(latitude, longitude, elevation);
     }
diff --git a/gps/src/org/wamblee/gpx/gpx.xsd b/gps/src/org/wamblee/gpx/gpx.xsd
new file mode 100644 (file)
index 0000000..0ce1605
--- /dev/null
@@ -0,0 +1,788 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<xsd:schema\r
+       xmlns:xsd="http://www.w3.org/2001/XMLSchema"\r
+       xmlns="http://www.topografix.com/GPX/1/1"\r
+       targetNamespace="http://www.topografix.com/GPX/1/1"\r
+       elementFormDefault="qualified">\r
+\r
+<xsd:annotation>\r
+ <xsd:documentation>\r
+  GPX schema version 1.1 - For more information on GPX and this schema, visit http://www.topografix.com/gpx.asp\r
+\r
+  GPX uses the following conventions: all coordinates are relative to the WGS84 datum.  All measurements are in metric units.\r
+ </xsd:documentation>\r
+</xsd:annotation>\r
+\r
+  <xsd:element name="gpx"      type="gpxType">\r
+    <xsd:annotation>\r
+      <xsd:documentation>\r
+               GPX is the root element in the XML file.\r
+         </xsd:documentation>\r
+       </xsd:annotation>\r
+  </xsd:element>\r
+\r
+  <xsd:complexType name="gpxType">\r
+    <xsd:annotation>\r
+      <xsd:documentation>\r
+               GPX documents contain a metadata header, followed by waypoints, routes, and tracks.  You can add your own elements\r
+               to the extensions section of the GPX document.\r
+         </xsd:documentation>\r
+       </xsd:annotation>\r
+       <xsd:sequence>\r
+        <xsd:element name="metadata"   type="metadataType"     minOccurs="0">\r
+         <xsd:annotation>\r
+          <xsd:documentation>\r
+               Metadata about the file.\r
+          </xsd:documentation>\r
+         </xsd:annotation>\r
+        </xsd:element>\r
+        <xsd:element name="wpt"                        type="wptType"  minOccurs="0" maxOccurs="unbounded">\r
+         <xsd:annotation>\r
+          <xsd:documentation>\r
+               A list of waypoints.\r
+          </xsd:documentation>\r
+         </xsd:annotation>\r
+        </xsd:element>\r
+        <xsd:element name="rte"                        type="rteType"  minOccurs="0" maxOccurs="unbounded">\r
+         <xsd:annotation>\r
+          <xsd:documentation>\r
+               A list of routes.\r
+          </xsd:documentation>\r
+         </xsd:annotation>\r
+        </xsd:element>\r
+        <xsd:element name="trk"                        type="trkType"  minOccurs="0" maxOccurs="unbounded">\r
+         <xsd:annotation>\r
+          <xsd:documentation>\r
+               A list of tracks.\r
+          </xsd:documentation>\r
+         </xsd:annotation>\r
+        </xsd:element>\r
+        <xsd:element name="extensions" type="extensionsType"   minOccurs="0">\r
+      <xsd:annotation>\r
+       <xsd:documentation>\r
+               You can add extend GPX by adding your own elements from another schema here.\r
+          </xsd:documentation>\r
+         </xsd:annotation>\r
+        </xsd:element>\r
+       </xsd:sequence>\r
+\r
+       <xsd:attribute name="version" type="xsd:string" use="required" fixed="1.1">\r
+     <xsd:annotation>\r
+      <xsd:documentation>\r
+               You must include the version number in your GPX document.\r
+         </xsd:documentation>\r
+        </xsd:annotation>\r
+       </xsd:attribute>\r
+       <xsd:attribute name="creator" type="xsd:string" use="required">\r
+     <xsd:annotation>\r
+      <xsd:documentation>\r
+               You must include the name or URL of the software that created your GPX document.  This allows others to\r
+               inform the creator of a GPX instance document that fails to validate.\r
+         </xsd:documentation>\r
+        </xsd:annotation>\r
+       </xsd:attribute>\r
+  </xsd:complexType>\r
+\r
+  <xsd:complexType name="metadataType">\r
+    <xsd:annotation>\r
+      <xsd:documentation>\r
+               Information about the GPX file, author, and copyright restrictions goes in the metadata section.  Providing rich,\r
+               meaningful information about your GPX files allows others to search for and use your GPS data.\r
+         </xsd:documentation>\r
+       </xsd:annotation>\r
+    <xsd:sequence>     <!-- elements must appear in this order -->\r
+     <xsd:element name="name"          type="xsd:string"               minOccurs="0">\r
+      <xsd:annotation>\r
+       <xsd:documentation>\r
+               The name of the GPX file.\r
+          </xsd:documentation>\r
+         </xsd:annotation>\r
+        </xsd:element>\r
+     <xsd:element name="desc"          type="xsd:string"               minOccurs="0">\r
+      <xsd:annotation>\r
+       <xsd:documentation>\r
+               A description of the contents of the GPX file.\r
+          </xsd:documentation>\r
+         </xsd:annotation>\r
+        </xsd:element>\r
+     <xsd:element name="author"                type="personType"               minOccurs="0">\r
+      <xsd:annotation>\r
+       <xsd:documentation>\r
+               The person or organization who created the GPX file.\r
+          </xsd:documentation>\r
+         </xsd:annotation>\r
+        </xsd:element>\r
+     <xsd:element name="copyright"     type="copyrightType"    minOccurs="0">\r
+      <xsd:annotation>\r
+       <xsd:documentation>\r
+               Copyright and license information governing use of the file.\r
+          </xsd:documentation>\r
+         </xsd:annotation>\r
+        </xsd:element>\r
+     <xsd:element name="link"          type="linkType"                 minOccurs="0" maxOccurs="unbounded">\r
+      <xsd:annotation>\r
+       <xsd:documentation>\r
+               URLs associated with the location described in the file.\r
+          </xsd:documentation>\r
+         </xsd:annotation>\r
+        </xsd:element>\r
+     <xsd:element name="time"          type="xsd:dateTime"             minOccurs="0">\r
+      <xsd:annotation>\r
+       <xsd:documentation>\r
+               The creation date of the file.\r
+          </xsd:documentation>\r
+         </xsd:annotation>\r
+        </xsd:element>\r
+     <xsd:element name="keywords"      type="xsd:string"               minOccurs="0">\r
+      <xsd:annotation>\r
+       <xsd:documentation>\r
+               Keywords associated with the file.  Search engines or databases can use this information to classify the data.\r
+          </xsd:documentation>\r
+         </xsd:annotation>\r
+        </xsd:element>\r
+     <xsd:element name="bounds"                type="boundsType"               minOccurs="0">\r
+      <xsd:annotation>\r
+       <xsd:documentation>\r
+               Minimum and maximum coordinates which describe the extent of the coordinates in the file.\r
+          </xsd:documentation>\r
+         </xsd:annotation>\r
+        </xsd:element>\r
+\r
+        <xsd:element name="extensions" type="extensionsType"   minOccurs="0">\r
+      <xsd:annotation>\r
+       <xsd:documentation>\r
+               You can add extend GPX by adding your own elements from another schema here.\r
+          </xsd:documentation>\r
+         </xsd:annotation>\r
+        </xsd:element>\r
+    </xsd:sequence>\r
+  </xsd:complexType>\r
+\r
+  <xsd:complexType name="wptType">\r
+    <xsd:annotation>\r
+      <xsd:documentation>\r
+               wpt represents a waypoint, point of interest, or named feature on a map.\r
+         </xsd:documentation>\r
+       </xsd:annotation>\r
+    <xsd:sequence>     <!-- elements must appear in this order -->\r
+         <!-- Position info -->\r
+      <xsd:element name="ele"                  type="xsd:decimal"              minOccurs="0">\r
+               <xsd:annotation>\r
+                 <xsd:documentation>\r
+                       Elevation (in meters) of the point.\r
+                 </xsd:documentation>\r
+               </xsd:annotation>\r
+         </xsd:element>\r
+      <xsd:element name="time"                 type="xsd:dateTime"             minOccurs="0">\r
+               <xsd:annotation>\r
+                 <xsd:documentation>\r
+                       Creation/modification timestamp for element. Date and time in are in Univeral Coordinated Time (UTC), not local time! Conforms to ISO 8601 specification for date/time representation. Fractional seconds are allowed for millisecond timing in tracklogs. \r
+                 </xsd:documentation>\r
+               </xsd:annotation>\r
+         </xsd:element>\r
+         <xsd:element name="magvar"            type="degreesType"              minOccurs="0">\r
+               <xsd:annotation>\r
+                 <xsd:documentation>\r
+                       Magnetic variation (in degrees) at the point\r
+                 </xsd:documentation>\r
+               </xsd:annotation>\r
+         </xsd:element>\r
+         <xsd:element name="geoidheight"       type="xsd:decimal"              minOccurs="0">\r
+               <xsd:annotation>\r
+                 <xsd:documentation>\r
+                       Height (in meters) of geoid (mean sea level) above WGS84 earth ellipsoid.  As defined in NMEA GGA message.\r
+                 </xsd:documentation>\r
+               </xsd:annotation>\r
+         </xsd:element>\r
+\r
+         <!-- Description info -->\r
+         <xsd:element name="name"                      type="xsd:string"               minOccurs="0">\r
+               <xsd:annotation>\r
+                 <xsd:documentation>\r
+                       The GPS name of the waypoint. This field will be transferred to and from the GPS. GPX does not place restrictions on the length of this field or the characters contained in it. It is up to the receiving application to validate the field before sending it to the GPS.\r
+                 </xsd:documentation>\r
+               </xsd:annotation>\r
+         </xsd:element>\r
+         <xsd:element name="cmt"                       type="xsd:string"               minOccurs="0">\r
+               <xsd:annotation>\r
+                 <xsd:documentation>\r
+                       GPS waypoint comment. Sent to GPS as comment. \r
+                 </xsd:documentation>\r
+               </xsd:annotation>\r
+         </xsd:element>\r
+         <xsd:element name="desc"                      type="xsd:string"               minOccurs="0">\r
+               <xsd:annotation>\r
+                 <xsd:documentation>\r
+                       A text description of the element. Holds additional information about the element intended for the user, not the GPS.\r
+                 </xsd:documentation>\r
+               </xsd:annotation>\r
+         </xsd:element>\r
+         <xsd:element name="src"                       type="xsd:string"               minOccurs="0">\r
+               <xsd:annotation>\r
+                 <xsd:documentation>\r
+                       Source of data. Included to give user some idea of reliability and accuracy of data.  "Garmin eTrex", "USGS quad Boston North", e.g.\r
+                 </xsd:documentation>\r
+               </xsd:annotation>\r
+         </xsd:element>\r
+      <xsd:element name="link"                 type="linkType"                 minOccurs="0" maxOccurs="unbounded">\r
+               <xsd:annotation>\r
+                 <xsd:documentation>\r
+                       Link to additional information about the waypoint.\r
+                 </xsd:documentation>\r
+               </xsd:annotation>\r
+         </xsd:element>\r
+         <xsd:element name="sym"                       type="xsd:string"               minOccurs="0">\r
+               <xsd:annotation>\r
+                 <xsd:documentation>\r
+                       Text of GPS symbol name. For interchange with other programs, use the exact spelling of the symbol as displayed on the GPS.  If the GPS abbreviates words, spell them out.\r
+                 </xsd:documentation>\r
+               </xsd:annotation>\r
+         </xsd:element>\r
+         <xsd:element name="type"                      type="xsd:string"               minOccurs="0">\r
+               <xsd:annotation>\r
+                 <xsd:documentation>\r
+                       Type (classification) of the waypoint.\r
+                 </xsd:documentation>\r
+               </xsd:annotation>\r
+         </xsd:element>\r
+\r
+         <!-- Accuracy info -->\r
+         <xsd:element name="fix"                       type="fixType"                  minOccurs="0">\r
+               <xsd:annotation>\r
+                 <xsd:documentation>\r
+                       Type of GPX fix.\r
+                 </xsd:documentation>\r
+               </xsd:annotation>\r
+         </xsd:element>\r
+         <xsd:element name="sat"                       type="xsd:nonNegativeInteger"   minOccurs="0">\r
+               <xsd:annotation>\r
+                 <xsd:documentation>\r
+                       Number of satellites used to calculate the GPX fix.\r
+                 </xsd:documentation>\r
+               </xsd:annotation>\r
+         </xsd:element>\r
+         <xsd:element name="hdop"                      type="xsd:decimal"              minOccurs="0">\r
+               <xsd:annotation>\r
+                 <xsd:documentation>\r
+                       Horizontal dilution of precision.\r
+                 </xsd:documentation>\r
+               </xsd:annotation>\r
+         </xsd:element>\r
+         <xsd:element name="vdop"                      type="xsd:decimal"              minOccurs="0">\r
+               <xsd:annotation>\r
+                 <xsd:documentation>\r
+                       Vertical dilution of precision.\r
+                 </xsd:documentation>\r
+               </xsd:annotation>\r
+         </xsd:element>\r
+         <xsd:element name="pdop"                      type="xsd:decimal"              minOccurs="0">\r
+               <xsd:annotation>\r
+                 <xsd:documentation>\r
+                       Position dilution of precision.\r
+                 </xsd:documentation>\r
+               </xsd:annotation>\r
+         </xsd:element>\r
+         <xsd:element name="ageofdgpsdata"     type="xsd:decimal"              minOccurs="0">\r
+               <xsd:annotation>\r
+                 <xsd:documentation>\r
+                       Number of seconds since last DGPS update.\r
+                 </xsd:documentation>\r
+               </xsd:annotation>\r
+         </xsd:element>\r
+         <xsd:element name="dgpsid"            type="dgpsStationType"  minOccurs="0">\r
+               <xsd:annotation>\r
+                 <xsd:documentation>\r
+                       ID of DGPS station used in differential correction.\r
+                 </xsd:documentation>\r
+               </xsd:annotation>\r
+         </xsd:element>\r
+\r
+        <xsd:element name="extensions"         type="extensionsType"   minOccurs="0">\r
+      <xsd:annotation>\r
+       <xsd:documentation>\r
+               You can add extend GPX by adding your own elements from another schema here.\r
+          </xsd:documentation>\r
+         </xsd:annotation>\r
+        </xsd:element>\r
+    </xsd:sequence>\r
+\r
+    <xsd:attribute name="lat"                  type="latitudeType"             use="required">\r
+        <xsd:annotation>\r
+         <xsd:documentation>\r
+               The latitude of the point.  Decimal degrees, WGS84 datum.\r
+         </xsd:documentation>\r
+        </xsd:annotation>\r
+       </xsd:attribute>\r
+    <xsd:attribute name="lon"                  type="longitudeType"    use="required">\r
+        <xsd:annotation>\r
+         <xsd:documentation>\r
+               The latitude of the point.  Decimal degrees, WGS84 datum.\r
+         </xsd:documentation>\r
+        </xsd:annotation>\r
+       </xsd:attribute>\r
+  </xsd:complexType>\r
+\r
+  <xsd:complexType name="rteType">\r
+    <xsd:annotation>\r
+      <xsd:documentation>\r
+               rte represents route - an ordered list of waypoints representing a series of turn points leading to a destination.\r
+         </xsd:documentation>\r
+       </xsd:annotation>\r
+    <xsd:sequence>\r
+      <xsd:element name="name"                 type="xsd:string"       minOccurs="0">\r
+               <xsd:annotation>\r
+                 <xsd:documentation>\r
+                       GPS name of route.\r
+                 </xsd:documentation>\r
+               </xsd:annotation>\r
+         </xsd:element>\r
+         <xsd:element name="cmt"                       type="xsd:string"       minOccurs="0">\r
+               <xsd:annotation>\r
+                 <xsd:documentation>\r
+                       GPS comment for route.\r
+                 </xsd:documentation>\r
+               </xsd:annotation>\r
+         </xsd:element>\r
+      <xsd:element name="desc"                 type="xsd:string"       minOccurs="0">\r
+               <xsd:annotation>\r
+                 <xsd:documentation>\r
+                       Text description of route for user.  Not sent to GPS.\r
+                 </xsd:documentation>\r
+               </xsd:annotation>\r
+         </xsd:element>\r
+         <xsd:element name="src"                       type="xsd:string"       minOccurs="0">\r
+               <xsd:annotation>\r
+                 <xsd:documentation>\r
+                       Source of data. Included to give user some idea of reliability and accuracy of data.\r
+                 </xsd:documentation>\r
+               </xsd:annotation>\r
+         </xsd:element>\r
+      <xsd:element name="link"                 type="linkType"         minOccurs="0" maxOccurs="unbounded">\r
+               <xsd:annotation>\r
+                 <xsd:documentation>\r
+                       Links to external information about the route.\r
+                 </xsd:documentation>\r
+               </xsd:annotation>\r
+         </xsd:element>\r
+         <xsd:element name="number"            type="xsd:nonNegativeInteger"   minOccurs="0">\r
+               <xsd:annotation>\r
+                 <xsd:documentation>\r
+                       GPS route number.\r
+                 </xsd:documentation>\r
+               </xsd:annotation>\r
+         </xsd:element>\r
+         <xsd:element name="type"                      type="xsd:string"       minOccurs="0">\r
+               <xsd:annotation>\r
+                 <xsd:documentation>\r
+                       Type (classification) of route.\r
+                 </xsd:documentation>\r
+               </xsd:annotation>\r
+         </xsd:element>\r
+\r
+        <xsd:element name="extensions"         type="extensionsType"   minOccurs="0">\r
+      <xsd:annotation>\r
+       <xsd:documentation>\r
+               You can add extend GPX by adding your own elements from another schema here.\r
+          </xsd:documentation>\r
+         </xsd:annotation>\r
+        </xsd:element>\r
\r
+      <xsd:element name="rtept"        type="wptType" minOccurs="0" maxOccurs="unbounded">\r
+         <xsd:annotation>\r
+          <xsd:documentation>\r
+               A list of route points.\r
+          </xsd:documentation>\r
+         </xsd:annotation>\r
+        </xsd:element>\r
+    </xsd:sequence>\r
+  </xsd:complexType>\r
+\r
+  <xsd:complexType name="trkType">\r
+    <xsd:annotation>\r
+      <xsd:documentation>\r
+               trk represents a track - an ordered list of points describing a path.\r
+         </xsd:documentation>\r
+       </xsd:annotation>\r
+    <xsd:sequence>\r
+      <xsd:element name="name"                 type="xsd:string"               minOccurs="0">\r
+               <xsd:annotation>\r
+                 <xsd:documentation>\r
+                       GPS name of track.\r
+                 </xsd:documentation>\r
+               </xsd:annotation>\r
+         </xsd:element>\r
+         <xsd:element name="cmt"                       type="xsd:string"               minOccurs="0">\r
+               <xsd:annotation>\r
+                 <xsd:documentation>\r
+                       GPS comment for track.\r
+                 </xsd:documentation>\r
+               </xsd:annotation>\r
+         </xsd:element>\r
+      <xsd:element name="desc"                 type="xsd:string"               minOccurs="0">\r
+               <xsd:annotation>\r
+                 <xsd:documentation>\r
+                       User description of track.\r
+                 </xsd:documentation>\r
+               </xsd:annotation>\r
+         </xsd:element>\r
+         <xsd:element name="src"                       type="xsd:string"               minOccurs="0">\r
+               <xsd:annotation>\r
+                 <xsd:documentation>\r
+                       Source of data. Included to give user some idea of reliability and accuracy of data.\r
+                 </xsd:documentation>\r
+               </xsd:annotation>\r
+         </xsd:element>\r
+      <xsd:element name="link"                 type="linkType"                 minOccurs="0" maxOccurs="unbounded">\r
+               <xsd:annotation>\r
+                 <xsd:documentation>\r
+                       Links to external information about track.\r
+                 </xsd:documentation>\r
+               </xsd:annotation>\r
+         </xsd:element>\r
+         <xsd:element name="number"            type="xsd:nonNegativeInteger"   minOccurs="0">\r
+               <xsd:annotation>\r
+                 <xsd:documentation>\r
+                       GPS track number.\r
+                 </xsd:documentation>\r
+               </xsd:annotation>\r
+         </xsd:element>\r
+         <xsd:element name="type"                      type="xsd:string"               minOccurs="0">\r
+               <xsd:annotation>\r
+                 <xsd:documentation>\r
+                       Type (classification) of track.\r
+                 </xsd:documentation>\r
+               </xsd:annotation>\r
+         </xsd:element>\r
+\r
+        <xsd:element name="extensions" type="extensionsType"   minOccurs="0">\r
+      <xsd:annotation>\r
+       <xsd:documentation>\r
+               You can add extend GPX by adding your own elements from another schema here.\r
+          </xsd:documentation>\r
+         </xsd:annotation>\r
+        </xsd:element>\r
+  \r
+     <xsd:element name="trkseg"                type="trksegType"               minOccurs="0" maxOccurs="unbounded">\r
+      <xsd:annotation>\r
+       <xsd:documentation>\r
+               A Track Segment holds a list of Track Points which are logically connected in order. To represent a single GPS track where GPS reception was lost, or the GPS receiver was turned off, start a new Track Segment for each continuous span of track data.\r
+          </xsd:documentation>\r
+         </xsd:annotation>\r
+        </xsd:element>\r
+    </xsd:sequence>\r
+  </xsd:complexType>\r
\r
+  <xsd:complexType name="extensionsType">\r
+   <xsd:annotation>\r
+    <xsd:documentation>\r
+        You can add extend GPX by adding your own elements from another schema here.\r
+    </xsd:documentation>\r
+   </xsd:annotation>\r
+    <xsd:sequence>\r
+        <xsd:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded">\r
+          <xsd:annotation>\r
+               <xsd:documentation>\r
+                You can add extend GPX by adding your own elements from another schema here.\r
+               </xsd:documentation>\r
+          </xsd:annotation>\r
+        </xsd:any>\r
+    </xsd:sequence>\r
+  </xsd:complexType>\r
+\r
+  <xsd:complexType name="trksegType">\r
+   <xsd:annotation>\r
+    <xsd:documentation>\r
+        A Track Segment holds a list of Track Points which are logically connected in order. To represent a single GPS track where GPS reception was lost, or the GPS receiver was turned off, start a new Track Segment for each continuous span of track data.\r
+    </xsd:documentation>\r
+   </xsd:annotation>\r
+   <xsd:sequence>      <!-- elements must appear in this order -->\r
+        <xsd:element name="trkpt"      type="wptType" minOccurs="0" maxOccurs="unbounded">\r
+      <xsd:annotation>\r
+       <xsd:documentation>\r
+               A Track Point holds the coordinates, elevation, timestamp, and metadata for a single point in a track.\r
+          </xsd:documentation>\r
+         </xsd:annotation>\r
+        </xsd:element>\r
+\r
+        <xsd:element name="extensions" type="extensionsType"   minOccurs="0">\r
+      <xsd:annotation>\r
+       <xsd:documentation>\r
+               You can add extend GPX by adding your own elements from another schema here.\r
+          </xsd:documentation>\r
+         </xsd:annotation>\r
+        </xsd:element>\r
+    </xsd:sequence>\r
+  </xsd:complexType>\r
+\r
+  <xsd:complexType name="copyrightType">\r
+   <xsd:annotation>\r
+    <xsd:documentation>\r
+        Information about the copyright holder and any license governing use of this file.  By linking to an appropriate license,\r
+        you may place your data into the public domain or grant additional usage rights.\r
+    </xsd:documentation>\r
+   </xsd:annotation>\r
+   <xsd:sequence>      <!-- elements must appear in this order -->\r
+    <xsd:element name="year"           type="xsd:gYear"        minOccurs="0">\r
+        <xsd:annotation>\r
+         <xsd:documentation>\r
+               Year of copyright.\r
+         </xsd:documentation>\r
+        </xsd:annotation>\r
+       </xsd:element>\r
+    <xsd:element name="license"                type="xsd:anyURI"       minOccurs="0">\r
+        <xsd:annotation>\r
+         <xsd:documentation>\r
+               Link to external file containing license text.\r
+         </xsd:documentation>\r
+        </xsd:annotation>\r
+       </xsd:element>\r
+   </xsd:sequence>\r
+   <xsd:attribute name="author" type="xsd:string" use="required">\r
+        <xsd:annotation>\r
+         <xsd:documentation>\r
+               Copyright holder (TopoSoft, Inc.)\r
+         </xsd:documentation>\r
+        </xsd:annotation>\r
+       </xsd:attribute>\r
+  </xsd:complexType>\r
+\r
+  <xsd:complexType name="linkType">\r
+   <xsd:annotation>\r
+    <xsd:documentation>\r
+        A link to an external resource (Web page, digital photo, video clip, etc) with additional information.\r
+    </xsd:documentation>\r
+   </xsd:annotation>\r
+   <xsd:sequence>      <!-- elements must appear in this order -->\r
+    <xsd:element name="text"           type="xsd:string"               minOccurs="0">\r
+        <xsd:annotation>\r
+         <xsd:documentation>\r
+               Text of hyperlink.\r
+         </xsd:documentation>\r
+        </xsd:annotation>\r
+       </xsd:element>\r
+    <xsd:element name="type"           type="xsd:string"               minOccurs="0">\r
+        <xsd:annotation>\r
+         <xsd:documentation>\r
+               Mime type of content (image/jpeg)\r
+         </xsd:documentation>\r
+        </xsd:annotation>\r
+       </xsd:element>\r
+   </xsd:sequence>\r
+   <xsd:attribute name="href" type="xsd:anyURI" use="required">\r
+        <xsd:annotation>\r
+         <xsd:documentation>\r
+               URL of hyperlink.\r
+         </xsd:documentation>\r
+        </xsd:annotation>\r
+       </xsd:attribute>\r
+  </xsd:complexType>\r
+\r
+  <xsd:complexType name="emailType">\r
+   <xsd:annotation>\r
+    <xsd:documentation>\r
+        An email address.  Broken into two parts (id and domain) to help prevent email harvesting.\r
+    </xsd:documentation>\r
+   </xsd:annotation>\r
+   <xsd:attribute name="id"                    type="xsd:string"               use="required">\r
+        <xsd:annotation>\r
+         <xsd:documentation>\r
+               id half of email address (billgates2004)\r
+         </xsd:documentation>\r
+        </xsd:annotation>\r
+       </xsd:attribute>\r
+   <xsd:attribute name="domain"                type="xsd:string"               use="required">\r
+        <xsd:annotation>\r
+         <xsd:documentation>\r
+               domain half of email address (hotmail.com)\r
+         </xsd:documentation>\r
+        </xsd:annotation>\r
+       </xsd:attribute>\r
+  </xsd:complexType>\r
+\r
+  <xsd:complexType name="personType">\r
+   <xsd:annotation>\r
+    <xsd:documentation>\r
+        A person or organization.\r
+    </xsd:documentation>\r
+   </xsd:annotation>\r
+    <xsd:sequence>     <!-- elements must appear in this order -->\r
+      <xsd:element name="name"         type="xsd:string"               minOccurs="0">\r
+        <xsd:annotation>\r
+         <xsd:documentation>\r
+               Name of person or organization.\r
+         </xsd:documentation>\r
+        </xsd:annotation>\r
+       </xsd:element>\r
+      <xsd:element name="email"                type="emailType"                minOccurs="0">\r
+        <xsd:annotation>\r
+         <xsd:documentation>\r
+               Email address.\r
+         </xsd:documentation>\r
+        </xsd:annotation>\r
+       </xsd:element>\r
+      <xsd:element name="link"         type="linkType"                 minOccurs="0">\r
+        <xsd:annotation>\r
+         <xsd:documentation>\r
+               Link to Web site or other external information about person.\r
+         </xsd:documentation>\r
+        </xsd:annotation>\r
+       </xsd:element>\r
+       </xsd:sequence>\r
+  </xsd:complexType>\r
+\r
+  <xsd:complexType name="ptType">\r
+   <xsd:annotation>\r
+    <xsd:documentation>\r
+        A geographic point with optional elevation and time.  Available for use by other schemas.\r
+    </xsd:documentation>\r
+   </xsd:annotation>\r
+   <xsd:sequence>      <!-- elements must appear in this order -->\r
+    <xsd:element name="ele"                    type="xsd:decimal"              minOccurs="0">\r
+        <xsd:annotation>\r
+         <xsd:documentation>\r
+               The elevation (in meters) of the point.\r
+         </xsd:documentation>\r
+        </xsd:annotation>\r
+       </xsd:element>\r
+    <xsd:element name="time"           type="xsd:dateTime"             minOccurs="0">\r
+        <xsd:annotation>\r
+         <xsd:documentation>\r
+               The time that the point was recorded.\r
+         </xsd:documentation>\r
+        </xsd:annotation>\r
+       </xsd:element>\r
+   </xsd:sequence>\r
+    <xsd:attribute name="lat"                  type="latitudeType"             use="required">\r
+        <xsd:annotation>\r
+         <xsd:documentation>\r
+               The latitude of the point.  Decimal degrees, WGS84 datum.\r
+         </xsd:documentation>\r
+        </xsd:annotation>\r
+       </xsd:attribute>\r
+    <xsd:attribute name="lon"                  type="longitudeType"    use="required">\r
+        <xsd:annotation>\r
+         <xsd:documentation>\r
+               The latitude of the point.  Decimal degrees, WGS84 datum.\r
+         </xsd:documentation>\r
+        </xsd:annotation>\r
+       </xsd:attribute>\r
+  </xsd:complexType>\r
+\r
+  <xsd:complexType name="ptsegType">\r
+   <xsd:annotation>\r
+    <xsd:documentation>\r
+        An ordered sequence of points.  (for polygons or polylines, e.g.)\r
+    </xsd:documentation>\r
+   </xsd:annotation>\r
+   <xsd:sequence>      <!-- elements must appear in this order -->\r
+        <xsd:element name="pt" type="ptType"   minOccurs="0" maxOccurs="unbounded">\r
+          <xsd:annotation>\r
+               <xsd:documentation>\r
+                Ordered list of geographic points.\r
+               </xsd:documentation>\r
+          </xsd:annotation>\r
+        </xsd:element>\r
+   </xsd:sequence>\r
+  </xsd:complexType>\r
+\r
+  <xsd:complexType name="boundsType">\r
+   <xsd:annotation>\r
+    <xsd:documentation>\r
+        Two lat/lon pairs defining the extent of an element.\r
+    </xsd:documentation>\r
+   </xsd:annotation>\r
+    <xsd:attribute name="minlat"               type="latitudeType"             use="required">\r
+        <xsd:annotation>\r
+         <xsd:documentation>\r
+               The minimum latitude.\r
+         </xsd:documentation>\r
+        </xsd:annotation>\r
+       </xsd:attribute>\r
+    <xsd:attribute name="minlon"               type="longitudeType"    use="required">\r
+        <xsd:annotation>\r
+         <xsd:documentation>\r
+               The minimum longitude.\r
+         </xsd:documentation>\r
+        </xsd:annotation>\r
+       </xsd:attribute>\r
+    <xsd:attribute name="maxlat"               type="latitudeType"             use="required">\r
+        <xsd:annotation>\r
+         <xsd:documentation>\r
+               The maximum latitude.\r
+         </xsd:documentation>\r
+        </xsd:annotation>\r
+       </xsd:attribute>\r
+    <xsd:attribute name="maxlon"               type="longitudeType"    use="required">\r
+        <xsd:annotation>\r
+         <xsd:documentation>\r
+               The maximum longitude.\r
+         </xsd:documentation>\r
+        </xsd:annotation>\r
+       </xsd:attribute>\r
+  </xsd:complexType>\r
+\r
+\r
+  <xsd:simpleType name="latitudeType">\r
+        <xsd:annotation>\r
+         <xsd:documentation>\r
+               The latitude of the point.  Decimal degrees, WGS84 datum.\r
+         </xsd:documentation>\r
+        </xsd:annotation>\r
+    <xsd:restriction base="xsd:decimal">\r
+      <xsd:minInclusive value="-90.0"/>\r
+      <xsd:maxInclusive value="90.0"/>\r
+    </xsd:restriction>\r
+  </xsd:simpleType>\r
+\r
+  <xsd:simpleType name="longitudeType">\r
+        <xsd:annotation>\r
+         <xsd:documentation>\r
+               The longitude of the point.  Decimal degrees, WGS84 datum.\r
+         </xsd:documentation>\r
+        </xsd:annotation>\r
+    <xsd:restriction base="xsd:decimal">\r
+      <xsd:minInclusive value="-180.0"/>\r
+      <xsd:maxExclusive value="180.0"/>\r
+    </xsd:restriction>\r
+  </xsd:simpleType>\r
+\r
+  <xsd:simpleType name="degreesType">\r
+        <xsd:annotation>\r
+         <xsd:documentation>\r
+               Used for bearing, heading, course.  Units are decimal degrees, true (not magnetic).\r
+         </xsd:documentation>\r
+        </xsd:annotation>\r
+    <xsd:restriction base="xsd:decimal">\r
+      <xsd:minInclusive value="0.0"/>\r
+      <xsd:maxExclusive value="360.0"/>\r
+    </xsd:restriction>\r
+  </xsd:simpleType>\r
+\r
+  <xsd:simpleType name="fixType">\r
+        <xsd:annotation>\r
+         <xsd:documentation>\r
+               Type of GPS fix.  none means GPS had no fix.  To signify "the fix info is unknown, leave out fixType entirely. pps = military signal used\r
+         </xsd:documentation>\r
+        </xsd:annotation>\r
+    <xsd:restriction base="xsd:string">\r
+      <xsd:enumeration value="none"/>\r
+      <xsd:enumeration value="2d"/>\r
+      <xsd:enumeration value="3d"/>\r
+      <xsd:enumeration value="dgps"/>\r
+      <xsd:enumeration value="pps"/>\r
+    </xsd:restriction>\r
+  </xsd:simpleType>\r
+\r
+  <xsd:simpleType name="dgpsStationType">\r
+   <xsd:annotation>\r
+    <xsd:documentation>\r
+        Represents a differential GPS station.\r
+    </xsd:documentation>\r
+   </xsd:annotation>\r
+    <xsd:restriction base="xsd:integer">\r
+      <xsd:minInclusive value="0"/>\r
+      <xsd:maxInclusive value="1023"/>\r
+    </xsd:restriction>\r
+  </xsd:simpleType>\r
+\r
+</xsd:schema>\r
index 05eae128640fa9b70a829a7e7c33814e379ca891..5651e34137f8caeec1c419a630a6840a947b1a82 100644 (file)
@@ -12,7 +12,7 @@
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
- */ 
+ */
 
 package org.wamblee.xml;
 
@@ -26,9 +26,13 @@ import java.util.List;
 import java.util.Map;
 import java.util.TreeMap;
 
+import javax.xml.XMLConstants;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -45,84 +49,160 @@ import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 import org.xml.sax.SAXException;
 
+import com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl;
+import com.sun.org.apache.xerces.internal.jaxp.validation.xs.SchemaFactoryImpl;
+
 /**
- * Some basic XML utilities for common reoccuring tasks for 
- * DOM documents.  
+ * Some basic XML utilities for common reoccuring tasks for DOM documents.
  */
 public final class DomUtils {
-    
+
     private static final Log LOG = LogFactory.getLog(DomUtils.class);
-    
+
     /**
-     * Disabled default constructor. 
-     *
+     * Disabled default constructor.
+     * 
      */
-    private DomUtils() { 
-        // Empty. 
+    private DomUtils() {
+        // Empty.
     }
-    
+
     /**
-     * Parses an XML document from a string. 
-     * @param aDocument document. 
-     * @return 
+     * Parses an XML document from a string.
+     * 
+     * @param aDocument
+     *            document.
+     * @return
      */
-    public static Document read(String aDocument) throws SAXException, ParserConfigurationException, IOException {
+    public static Document read(String aDocument) throws XMLException {
         ByteArrayInputStream is = new ByteArrayInputStream(aDocument.getBytes());
-        return read(is);          
+        return read(is);
     }
-    
+
     /**
-     * Parses an XML document from a stream. 
-     * @param aIs Input stream. 
+     * Parses an XML document from a stream.
+     * 
+     * @param aIs
+     *            Input stream.
      * @return
      */
-    public static Document read(InputStream aIs) throws SAXException, ParserConfigurationException, IOException { 
-        DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); 
-        return builder.parse(aIs);     
+    public static Document read(InputStream aIs) throws XMLException {
+        try {
+            DocumentBuilder builder = DocumentBuilderFactory.newInstance()
+                    .newDocumentBuilder();
+            return builder.parse(aIs);
+        }  catch (SAXException e) {
+            throw new XMLException(e.getMessage(), e);
+        } catch (IOException e) {
+            throw new XMLException(e.getMessage(), e);
+        } catch (ParserConfigurationException e) {
+            throw new XMLException(e.getMessage(), e);
+        } finally {
+            try {
+                aIs.close();
+            } catch (Exception e) {
+                LOG.warn("Error closing XML file", e);
+            }
+        }
     }
 
     /**
-     * Serializes an XML document to a stream. 
-     * @param aDocument Document to serialize. 
-     * @param aOs Output stream. 
+     * Reads and validates a document against a schema.
+     * 
+     * @param aIs
+     *            Input stream.
+     * @param aSchema
+     *            Schema.
+     * @return Parsed and validated document.
      */
-    public static void serialize(Document aDocument, OutputStream aOs) throws IOException { 
+    public static Document readAndValidate(InputStream aIs, InputStream aSchema)
+            throws XMLException {
+
+        try {
+            final Schema schema = SchemaFactory.newInstance(
+                    XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema(
+                    new StreamSource(aSchema));
+
+            final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+            factory.setValidating(true);
+            factory.setNamespaceAware(true);
+            factory.setSchema(schema);
+
+            return factory.newDocumentBuilder().parse(aIs);
+        } catch (SAXException e) {
+            throw new XMLException(e.getMessage(), e);
+        } catch (IOException e) {
+            throw new XMLException(e.getMessage(), e);
+        } catch (ParserConfigurationException e) {
+            throw new XMLException(e.getMessage(), e);
+        } finally {
+            try {
+                aSchema.close();
+            } catch (Exception e) {
+                LOG.warn("Error closing schema", e);
+            }
+            try {
+                aIs.close();
+            } catch (Exception e) {
+                LOG.warn("Error closing XML file", e);
+            }
+        }
+
+    }
+
+    /**
+     * Serializes an XML document to a stream.
+     * 
+     * @param aDocument
+     *            Document to serialize.
+     * @param aOs
+     *            Output stream.
+     */
+    public static void serialize(Document aDocument, OutputStream aOs)
+            throws IOException {
         XMLSerializer serializer = new XMLSerializer(aOs, new OutputFormat());
         serializer.serialize(aDocument);
     }
-    
+
     /**
-     * Serializes an XML document. 
-     * @param aDocument Document to serialize. 
-     * @return Serialized document. 
+     * Serializes an XML document.
+     * 
+     * @param aDocument
+     *            Document to serialize.
+     * @return Serialized document.
      */
     public static String serialize(Document aDocument) throws IOException {
         ByteArrayOutputStream os = new ByteArrayOutputStream();
-        serialize(aDocument, os); 
-        return os.toString(); 
+        serialize(aDocument, os);
+        return os.toString();
     }
-    
+
     /**
-     * Converts a dom4j document into a w3c DOM document. 
-     * @param aDocument Document to convert. 
-     * @return W3C DOM document. 
+     * Converts a dom4j document into a w3c DOM document.
+     * 
+     * @param aDocument
+     *            Document to convert.
+     * @return W3C DOM document.
      */
-    public static Document convert(org.dom4j.Document aDocument) throws DocumentException {
+    public static Document convert(org.dom4j.Document aDocument)
+            throws DocumentException {
         return new DOMWriter().write(aDocument);
     }
 
     /**
-     * Converts a W3C DOM document into a dom4j document. 
-     * @param aDocument Document to convert. 
+     * Converts a W3C DOM document into a dom4j document.
+     * 
+     * @param aDocument
+     *            Document to convert.
      * @return Dom4j document.
      */
-    public static org.dom4j.Document convert(Document aDocument) { 
-        return new DOMReader().read(aDocument); 
+    public static org.dom4j.Document convert(Document aDocument) {
+        return new DOMReader().read(aDocument);
     }
-    
+
     /**
-     * Removes duplicate attributes from a DOM tree.This is useful for postprocessing the
-     * output of JTidy as a workaround for a bug in JTidy. 
+     * Removes duplicate attributes from a DOM tree.This is useful for
+     * postprocessing the output of JTidy as a workaround for a bug in JTidy.
      * 
      * @param aNode
      *            Node to remove duplicate attributes from (recursively).
diff --git a/support/src/org/wamblee/xml/XMLException.java b/support/src/org/wamblee/xml/XMLException.java
new file mode 100644 (file)
index 0000000..53f1d5e
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2006 the original author or authors.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */ 
+
+package org.wamblee.xml;
+
+/**
+ * Exception thrown in case of XML parsing problems.  
+ */
+public class XMLException extends Exception {
+
+    public XMLException(String aMsg) { 
+        super(aMsg); 
+    }
+    
+    public XMLException(String aMsg, Throwable aCause) { 
+        super(aMsg, aCause);
+    }
+}