com.hs.gpxparser.GPXParser Maven / Gradle / Ivy
package com.hs.gpxparser;
import java.io.InputStream;
import java.text.ParseException;
import java.util.Date;
import java.util.Iterator;
import java.util.regex.Pattern;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.hs.gpxparser.extension.DummyExtensionParser;
import com.hs.gpxparser.extension.IExtensionParser;
import com.hs.gpxparser.modal.Bounds;
import com.hs.gpxparser.modal.Copyright;
import com.hs.gpxparser.modal.Email;
import com.hs.gpxparser.modal.GPX;
import com.hs.gpxparser.modal.Link;
import com.hs.gpxparser.modal.Metadata;
import com.hs.gpxparser.modal.Person;
import com.hs.gpxparser.modal.Route;
import com.hs.gpxparser.modal.Track;
import com.hs.gpxparser.modal.TrackSegment;
import com.hs.gpxparser.modal.Waypoint;
import com.hs.gpxparser.type.Fix;
/**
*
* This class defines methods for parsing and writing gpx files.
*
*
* Usage for parsing a gpx file into a {@link GPX} object:
*
* GPXParser p = new GPXParser();
* FileInputStream in = new FileInputStream("inFile.gpx");
* GPX gpx = p.parseGPX(in);
*
* Usage for writing a {@link GPX} object to a file:
*
* GPXParser p = new GPXParser();
* FileOutputStream out = new FileOutputStream("outFile.gpx");
* p.writeGPX(gpx, out);
* out.close();
*
*/
public class GPXParser extends BaseGPX {
// TFE, 20180109: use pattern for parsing to improve performance
private final static Pattern datevaluePattern = Pattern.compile("([0-9\\-T]+:[0-9]{2}:[0-9.+]+):([0-9]{2})");
/**
* Parses a stream containing GPX data
*
* @param in
* the input stream
* @return {@link GPX} object containing parsed data, or null if no gpx data
* was found in the seream
* @throws Exception
* when error
*/
public GPX parseGPX(InputStream in) throws Exception {
// TFE, 20180217: add default parser if none set
if (this.extensionParsers.isEmpty()) {
this.extensionParsers.add(new DummyExtensionParser());
}
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = builder.parse(in);
Node firstChild = doc.getFirstChild();
if (firstChild != null && GPXConstants.NODE_GPX.equals(firstChild.getNodeName())) {
GPX gpx = new GPX();
NamedNodeMap attrs = firstChild.getAttributes();
for (int idx = 0; idx < attrs.getLength(); idx++) {
Node attr = attrs.item(idx);
if (GPXConstants.ATTR_VERSION.equals(attr.getNodeName())) {
gpx.setVersion(attr.getNodeValue());
} else if (GPXConstants.ATTR_CREATOR.equals(attr.getNodeName())) {
gpx.setCreator(attr.getNodeValue());
// TFE, 20180201: support multiple xmlns attributes
} else if (attr.getNodeName().startsWith(GPXConstants.ATTR_XMLNS)) {
gpx.addXmlns(attr.getNodeName(), attr.getNodeValue());
}
}
NodeList nodes = firstChild.getChildNodes();
for (int idx = 0; idx < nodes.getLength(); idx++) {
Node currentNode = nodes.item(idx);
if (GPXConstants.NODE_METADATA.equals(currentNode.getNodeName())) {
Metadata m = this.parseMetadata(currentNode);
if (m != null) {
gpx.setMetadata(m);
}
} else if (GPXConstants.NODE_WPT.equals(currentNode.getNodeName())) {
Waypoint w = this.parseWaypoint(currentNode);
if (w != null) {
gpx.addWaypoint(w);
}
} else if (GPXConstants.NODE_RTE.equals(currentNode.getNodeName())) {
Route rte = this.parseRoute(currentNode);
if (rte != null) {
gpx.addRoute(rte);
}
} else if (GPXConstants.NODE_TRK.equals(currentNode.getNodeName())) {
Track trk = this.parseTrack(currentNode);
if (trk != null) {
gpx.addTrack(trk);
}
} else if (GPXConstants.NODE_EXTENSIONS.equals(currentNode.getNodeName())) {
for (IExtensionParser parser : this.extensionParsers) {
Object data = parser.parseExtensions(currentNode);
gpx.addExtensionData(parser.getId(), data);
}
}
}
return gpx;
} else {
throw new IllegalAccessException("Not a valid GPX file.");
}
}
private Metadata parseMetadata(Node node) throws DOMException, ParseException {
if (node == null) {
return null;
}
Metadata m = new Metadata();
NodeList childNodes = node.getChildNodes();
if (childNodes != null) {
for (int idx = 0; idx < childNodes.getLength(); idx++) {
Node currentNode = childNodes.item(idx);
if (GPXConstants.NODE_NAME.equals(currentNode.getNodeName())) {
m.setName(this.getNodeValueAsString(currentNode));
} else if (GPXConstants.NODE_DESC.equals(currentNode.getNodeName())) {
m.setDesc(this.getNodeValueAsString(currentNode));
} else if (GPXConstants.NODE_AUTHOR.equals(currentNode.getNodeName())) {
Person author = this.parsePerson(currentNode);
if (author != null) {
m.setAuthor(author);
}
} else if (GPXConstants.NODE_COPYRIGHT.equals(currentNode.getNodeName())) {
Copyright copyright = this.parseCopyright(currentNode);
if (copyright != null) {
m.setCopyright(copyright);
}
} else if (GPXConstants.NODE_LINK.equals(currentNode.getNodeName())) {
Link link = this.parseLink(currentNode);
if (link != null) {
m.addLink(link);
}
} else if (GPXConstants.NODE_TIME.equals(currentNode.getNodeName())) {
m.setTime(this.getNodeValueAsDate(currentNode));
} else if (GPXConstants.NODE_KEYWORDS.equals(currentNode.getNodeName())) {
m.setKeywords(this.getNodeValueAsString(currentNode));
} else if (GPXConstants.NODE_BOUNDS.equals(currentNode.getNodeName())) {
Bounds bounds = this.parseBounds(currentNode);
if (bounds != null) {
m.setBounds(bounds);
}
} else if (GPXConstants.NODE_EXTENSIONS.equals(currentNode.getNodeName())) {
Iterator it = this.extensionParsers.iterator();
while (it.hasNext()) {
IExtensionParser parser = it.next();
Object data = parser.parseExtensions(currentNode);
m.addExtensionData(parser.getId(), data);
}
}
}
}
return m;
}
private Person parsePerson(Node node) {
if (node == null) {
return null;
}
Person p = new Person();
NodeList childNodes = node.getChildNodes();
if (childNodes != null) {
for (int idx = 0; idx < childNodes.getLength(); idx++) {
Node currentNode = childNodes.item(idx);
if (GPXConstants.NODE_NAME.equals(currentNode.getNodeName())) {
p.setName(this.getNodeValueAsString(currentNode));
} else if (GPXConstants.NODE_EMAIL.equals(currentNode.getNodeName())) {
Email email = this.parseEmail(currentNode);
if (email != null) {
p.setEmail(email);
}
} else if (GPXConstants.NODE_LINK.equals(currentNode.getNodeName())) {
Link link = this.parseLink(currentNode);
if (link != null) {
p.setLink(link);
}
}
}
}
return p;
}
private Copyright parseCopyright(Node node) {
if (node == null) {
return null;
}
Copyright c = new Copyright(null);
NamedNodeMap attrs = node.getAttributes();
for (int idx = 0; idx < attrs.getLength(); idx++) {
Node attr = attrs.item(idx);
if (GPXConstants.ATTR_AUTHOR.equals(attr.getNodeName())) {
c.setAuthor(attr.getNodeValue());
}
}
NodeList childNodes = node.getChildNodes();
if (childNodes != null) {
for (int idx = 0; idx < childNodes.getLength(); idx++) {
Node currentNode = childNodes.item(idx);
if (GPXConstants.NODE_YEAR.equals(currentNode.getNodeName())) {
c.setYear(this.getNodeValueAsString(currentNode));
} else if (GPXConstants.NODE_LICENSE.equals(currentNode.getNodeName())) {
c.setLicense(this.getNodeValueAsString(currentNode));
}
}
}
return c;
}
private Link parseLink(Node node) {
if (node == null) {
return null;
}
Link l = new Link(null);
NamedNodeMap attrs = node.getAttributes();
for (int idx = 0; idx < attrs.getLength(); idx++) {
Node attr = attrs.item(idx);
if (GPXConstants.ATTR_HREF.equals(attr.getNodeName())) {
l.setHref(attr.getNodeValue());
}
}
NodeList childNodes = node.getChildNodes();
if (childNodes != null) {
for (int idx = 0; idx < childNodes.getLength(); idx++) {
Node currentNode = childNodes.item(idx);
if (GPXConstants.NODE_TEXT.equals(currentNode.getNodeName())) {
l.setText(this.getNodeValueAsString(currentNode));
} else if (GPXConstants.NODE_TYPE.equals(currentNode.getNodeName())) {
l.setType(this.getNodeValueAsString(currentNode));
}
}
}
return l;
}
private Bounds parseBounds(Node node) {
if (node == null) {
return null;
}
Bounds b = new Bounds(0, 0, 0, 0);
NamedNodeMap attrs = node.getAttributes();
for (int idx = 0; idx < attrs.getLength(); idx++) {
Node attr = attrs.item(idx);
if (GPXConstants.ATTR_MINLAT.equals(attr.getNodeName())) {
b.setMinLat(Double.parseDouble(attr.getNodeValue()));
} else if (GPXConstants.ATTR_MINLON.equals(attr.getNodeName())) {
b.setMinLon(Double.parseDouble(attr.getNodeValue()));
} else if (GPXConstants.ATTR_MAXLAT.equals(attr.getNodeName())) {
b.setMaxLat(Double.parseDouble(attr.getNodeValue()));
} else if (GPXConstants.ATTR_MAXLON.equals(attr.getNodeName())) {
b.setMaxLon(Double.parseDouble(attr.getNodeValue()));
}
}
return b;
}
private Email parseEmail(Node node) {
if (node == null) {
return null;
}
Email e = new Email(null, null);
NamedNodeMap attrs = node.getAttributes();
for (int idx = 0; idx < attrs.getLength(); idx++) {
Node attr = attrs.item(idx);
if (GPXConstants.ATTR_ID.equals(attr.getNodeName())) {
e.setId(attr.getNodeValue());
} else if (GPXConstants.ATTR_DOMAIN.equals(attr.getNodeName())) {
e.setDomain(attr.getNodeValue());
}
}
return e;
}
private Waypoint parseWaypoint(Node node) throws Exception {
if (node == null) {
return null;
}
Waypoint w = new Waypoint(0, 0);
NamedNodeMap attrs = node.getAttributes();
// check for lat attribute
Node latNode = attrs.getNamedItem(GPXConstants.ATTR_LAT);
if (latNode != null) {
Double latVal = null;
latVal = Double.parseDouble(latNode.getNodeValue());
w.setLatitude(latVal);
} else {
throw new Exception("no lat value in waypoint data.");
}
// check for lon attribute
Node lonNode = attrs.getNamedItem(GPXConstants.ATTR_LON);
if (lonNode != null) {
Double lonVal = Double.parseDouble(lonNode.getNodeValue());
w.setLongitude(lonVal);
} else {
throw new Exception("no lon value in waypoint data.");
}
NodeList childNodes = node.getChildNodes();
if (childNodes != null) {
for (int idx = 0; idx < childNodes.getLength(); idx++) {
Node currentNode = childNodes.item(idx);
if (GPXConstants.NODE_ELE.equals(currentNode.getNodeName())) {
w.setElevation(this.getNodeValueAsDouble(currentNode));
} else if (GPXConstants.NODE_TIME.equals(currentNode.getNodeName())) {
w.setTime(this.getNodeValueAsDate(currentNode));
} else if (GPXConstants.NODE_MAGVAR.equals(currentNode.getNodeName())) {
w.setMagneticVariation(this.getNodeValueAsDouble(currentNode));
} else if (GPXConstants.NODE_GEOIDHEIGHT.equals(currentNode.getNodeName())) {
w.setGeoIdHeight(this.getNodeValueAsDouble(currentNode));
} else if (GPXConstants.NODE_NAME.equals(currentNode.getNodeName())) {
w.setName(this.getNodeValueAsString(currentNode));
} else if (GPXConstants.NODE_CMT.equals(currentNode.getNodeName())) {
w.setComment(this.getNodeValueAsString(currentNode));
} else if (GPXConstants.NODE_DESC.equals(currentNode.getNodeName())) {
w.setDescription(this.getNodeValueAsString(currentNode));
} else if (GPXConstants.NODE_SRC.equals(currentNode.getNodeName())) {
w.setSrc(this.getNodeValueAsString(currentNode));
} else if (GPXConstants.NODE_LINK.equals(currentNode.getNodeName())) {
Link link = this.parseLink(currentNode);
if (link != null) {
w.addLink(link);
}
} else if (GPXConstants.NODE_SYM.equals(currentNode.getNodeName())) {
w.setSym(this.getNodeValueAsString(currentNode));
} else if (GPXConstants.NODE_TYPE.equals(currentNode.getNodeName())) {
w.setType(this.getNodeValueAsString(currentNode));
} else if (GPXConstants.NODE_FIX.equals(currentNode.getNodeName())) {
w.setFix(this.getNodeValueAsFixType(currentNode));
} else if (GPXConstants.NODE_SAT.equals(currentNode.getNodeName())) {
w.setSat(this.getNodeValueAsInteger(currentNode));
} else if (GPXConstants.NODE_HDOP.equals(currentNode.getNodeName())) {
w.setHdop(this.getNodeValueAsDouble(currentNode));
} else if (GPXConstants.NODE_VDOP.equals(currentNode.getNodeName())) {
w.setVdop(this.getNodeValueAsDouble(currentNode));
} else if (GPXConstants.NODE_PDOP.equals(currentNode.getNodeName())) {
w.setPdop(this.getNodeValueAsDouble(currentNode));
} else if (GPXConstants.NODE_AGEOFGPSDATA.equals(currentNode.getNodeName())) {
w.setAgeOfGPSData(this.getNodeValueAsDouble(currentNode));
} else if (GPXConstants.NODE_DGPSID.equals(currentNode.getNodeName())) {
w.setdGpsStationId(this.getNodeValueAsInteger(currentNode));
} else if (GPXConstants.NODE_EXTENSIONS.equals(currentNode.getNodeName())) {
Iterator it = this.extensionParsers.iterator();
while (it.hasNext()) {
IExtensionParser parser = it.next();
Object data = parser.parseExtensions(currentNode);
w.addExtensionData(parser.getId(), data);
}
}
}
}
return w;
}
private Route parseRoute(Node node) throws Exception {
if (node == null) {
return null;
}
Route rte = new Route();
NodeList nodes = node.getChildNodes();
if (nodes != null) {
for (int idx = 0; idx < nodes.getLength(); idx++) {
Node currentNode = nodes.item(idx);
if (GPXConstants.NODE_NAME.equals(currentNode.getNodeName())) {
rte.setName(this.getNodeValueAsString(currentNode));
} else if (GPXConstants.NODE_CMT.equals(currentNode.getNodeName())) {
rte.setComment(this.getNodeValueAsString(currentNode));
} else if (GPXConstants.NODE_DESC.equals(currentNode.getNodeName())) {
rte.setDescription(this.getNodeValueAsString(currentNode));
} else if (GPXConstants.NODE_SRC.equals(currentNode.getNodeName())) {
rte.setSrc(this.getNodeValueAsString(currentNode));
} else if (GPXConstants.NODE_LINK.equals(currentNode.getNodeName())) {
Link link = this.parseLink(currentNode);
if (link != null) {
rte.addLink(link);
}
} else if (GPXConstants.NODE_NUMBER.equals(currentNode.getNodeName())) {
rte.setNumber(this.getNodeValueAsInteger(currentNode));
} else if (GPXConstants.NODE_TYPE.equals(currentNode.getNodeName())) {
rte.setType(this.getNodeValueAsString(currentNode));
} else if (GPXConstants.NODE_EXTENSIONS.equals(currentNode.getNodeName())) {
Iterator it = this.extensionParsers.iterator();
while (it.hasNext()) {
while (it.hasNext()) {
IExtensionParser parser = it.next();
Object data = parser.parseExtensions(currentNode);
rte.addExtensionData(parser.getId(), data);
}
}
} else if (GPXConstants.NODE_RTEPT.equals(currentNode.getNodeName())) {
Waypoint wp = this.parseWaypoint(currentNode);
if (wp != null) {
rte.addRoutePoint(wp);
}
}
}
}
return rte;
}
private Track parseTrack(Node node) throws Exception {
if (node == null) {
return null;
}
Track trk = new Track();
NodeList nodes = node.getChildNodes();
if (nodes != null) {
for (int idx = 0; idx < nodes.getLength(); idx++) {
Node currentNode = nodes.item(idx);
if (GPXConstants.NODE_NAME.equals(currentNode.getNodeName())) {
trk.setName(this.getNodeValueAsString(currentNode));
} else if (GPXConstants.NODE_CMT.equals(currentNode.getNodeName())) {
trk.setComment(this.getNodeValueAsString(currentNode));
} else if (GPXConstants.NODE_DESC.equals(currentNode.getNodeName())) {
trk.setDescription(this.getNodeValueAsString(currentNode));
} else if (GPXConstants.NODE_SRC.equals(currentNode.getNodeName())) {
trk.setSrc(this.getNodeValueAsString(currentNode));
} else if (GPXConstants.NODE_LINK.equals(currentNode.getNodeName())) {
Link link = this.parseLink(currentNode);
if (link != null) {
trk.addLink(link);
}
} else if (GPXConstants.NODE_NUMBER.equals(currentNode.getNodeName())) {
trk.setNumber(this.getNodeValueAsInteger(currentNode));
} else if (GPXConstants.NODE_TYPE.equals(currentNode.getNodeName())) {
trk.setType(this.getNodeValueAsString(currentNode));
} else if (GPXConstants.NODE_EXTENSIONS.equals(currentNode.getNodeName())) {
Iterator it = this.extensionParsers.iterator();
while (it.hasNext()) {
while (it.hasNext()) {
IExtensionParser parser = it.next();
Object data = parser.parseExtensions(currentNode);
trk.addExtensionData(parser.getId(), data);
}
}
} else if (GPXConstants.NODE_TRKSEG.equals(currentNode.getNodeName())) {
TrackSegment trackSeg = this.parseTrackSegment(currentNode);
if (trackSeg != null) {
trk.addTrackSegment(trackSeg);
}
}
}
}
return trk;
}
private TrackSegment parseTrackSegment(Node node) throws Exception {
if (node == null) {
return null;
}
TrackSegment ts = new TrackSegment();
NodeList childNodes = node.getChildNodes();
if (childNodes != null) {
for (int idx = 0; idx < childNodes.getLength(); idx++) {
Node currentNode = childNodes.item(idx);
if (GPXConstants.NODE_TRKPT.equals(currentNode.getNodeName())) {
Waypoint w = this.parseWaypoint(currentNode);
if (w != null) {
ts.addWaypoint(w);
}
} else if (GPXConstants.NODE_EXTENSIONS.equals(currentNode.getNodeName())) {
Iterator it = this.extensionParsers.iterator();
while (it.hasNext()) {
while (it.hasNext()) {
IExtensionParser parser = it.next();
Object data = parser.parseExtensions(currentNode);
ts.addExtensionData(parser.getId(), data);
}
}
}
}
}
return ts;
}
private Date getNodeValueAsDate(Node node) throws DOMException, ParseException {
Date val = null;
try {
// TFE, 20180109: use pre-compiled pattern instead of
// String.replaceAll
// val = xmlDateFormat.parse(node.getFirstChild().getNodeValue()
// .replaceAll("([0-9\\-T]+:[0-9]{2}:[0-9.+]+):([0-9]{2})",
// "$1$2"));
val = xmlDateFormat.parse(
datevaluePattern.matcher(node.getFirstChild().getNodeValue()).replaceAll("$1$2"));
}
catch (ParseException e) {
e.printStackTrace();
}
catch (Exception e) {
e.printStackTrace();
}
return val;
}
private Double getNodeValueAsDouble(Node node) {
return Double.parseDouble(node.getFirstChild().getNodeValue());
}
private Fix getNodeValueAsFixType(Node node) {
return Fix.returnType(node.getFirstChild().getNodeValue());
}
private Integer getNodeValueAsInteger(Node node) {
return Integer.parseInt(node.getFirstChild().getNodeValue());
}
private String getNodeValueAsString(Node node) {
if (node == null) {
return null;
}
Node child = node.getFirstChild();
if (child == null) {
return null;
}
return child.getNodeValue();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy