Index: src/org/openstreetmap/josm/actions/AboutAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/AboutAction.java	(revision 25)
+++ src/org/openstreetmap/josm/actions/AboutAction.java	(revision 27)
@@ -5,5 +5,4 @@
 import java.awt.GridBagLayout;
 import java.awt.event.ActionEvent;
-import java.awt.event.InputEvent;
 import java.awt.event.KeyEvent;
 import java.io.BufferedReader;
@@ -22,5 +21,4 @@
 import javax.swing.JTabbedPane;
 import javax.swing.JTextArea;
-import javax.swing.KeyStroke;
 import javax.swing.event.HyperlinkEvent;
 import javax.swing.event.HyperlinkListener;
Index: src/org/openstreetmap/josm/io/OsmReader.java
===================================================================
--- src/org/openstreetmap/josm/io/OsmReader.java	(revision 27)
+++ src/org/openstreetmap/josm/io/OsmReader.java	(revision 27)
@@ -0,0 +1,212 @@
+package org.openstreetmap.josm.io;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.StringTokenizer;
+
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.jdom.input.SAXBuilder;
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.GeoPoint;
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.Key;
+import org.openstreetmap.josm.data.osm.LineSegment;
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.Track;
+
+/**
+ * Reads an osm xml stream and construct a DataSet out of it. 
+ * 
+ * @author imi
+ */
+public class OsmReader {
+
+	/**
+	 * The data source from this reader.
+	 */
+	public Reader source;
+
+	/**
+	 * Construct a parser from a specific data source.
+	 * @param source The data source, as example a FileReader to read from a file.
+	 */
+	public OsmReader(Reader source) {
+		this.source = source;
+	}
+	static int i;
+	/**
+	 * Read the input stream and return a DataSet from the stream.
+	 */
+	public DataSet parse() throws JDOMException, IOException {
+		try {
+			final SAXBuilder builder = new SAXBuilder();
+			Element root = builder.build(source).getRootElement();
+			return parseDataSet(root);
+		} catch (NullPointerException npe) {
+			throw new JDOMException("NullPointerException. Probably a tag name mismatch.", npe);
+		} catch (ClassCastException cce) {
+			throw new JDOMException("ClassCastException. Probably a tag does not contain the correct type.", cce);
+		}
+	}
+
+
+	/**
+	 * Read one node.
+	 * @param e 	The element to parse
+	 * @return		The Waypoint read from the element
+	 * @throws JDOMException In case of a parsing error.
+	 */
+	private Node parseNode(Element e) throws JDOMException {
+		Node data = new Node();
+		data.coor = new GeoPoint(
+			Float.parseFloat(e.getAttributeValue("lat")),
+			Float.parseFloat(e.getAttributeValue("lon")));
+		if (Double.isNaN(data.coor.lat) || 
+				data.coor.lat < -90 || data.coor.lat > 90 ||
+				data.coor.lon < -180 || data.coor.lon > 180)
+			throw new JDOMException("Illegal lat or lon value: "+data.coor.lat+"/"+data.coor.lon);
+		parseCommon(data, e);
+		return data;
+	}
+
+	/**
+	 * Parse the common part (properties and uid) of the element.
+	 * @param data	To store the data in. 
+	 * @param e		The element to extract the common information.
+	 * @throws JDOMException In case of a parsing error
+	 */
+	private void parseCommon(OsmPrimitive data, Element e) throws JDOMException {
+		data.id = Long.parseLong(e.getAttributeValue("uid"));
+		if (data.id == 0)
+			throw new JDOMException("Object has illegal or no id.");
+		
+		String propStr = e.getAttributeValue("tags");
+		if (propStr != null && !propStr.equals("")) {
+			data.keys = new HashMap<Key, String>();
+			StringTokenizer st = new StringTokenizer(propStr, ";");
+			while (st.hasMoreTokens()) {
+				StringTokenizer t = new StringTokenizer(st.nextToken(), "=");
+				if (t.countTokens() > 1)
+					data.keys.put(Key.get(t.nextToken()), t.nextToken());
+				else {
+					String token = t.nextToken();
+					if (!" ".equals(token))
+						data.keys.put(Key.get(t.nextToken()), "yes");
+				}
+			}
+		}
+	}
+
+	/**
+	 * Read a data set from the element.
+	 * @param e 	The element to parse
+	 * @return		The DataSet read from the element
+	 * @throws JDOMException In case of a parsing error.
+	 */
+	private DataSet parseDataSet(Element e) throws JDOMException {
+		DataSet data = new DataSet();
+		for (Object o : e.getChildren()) {
+			Element child = (Element)o;
+			if (child.getName().equals("node"))
+				addNode(data, parseNode(child));
+			else if (child.getName().equals("segment"))
+				data.pendingLineSegments.add(parseLineSegment(child, data));
+			else if (child.getName().equals("track"))
+				data.tracks.add(parseTrack(child, data));
+		}
+
+		return data;
+	}
+
+	/**
+	 * Parse and return an line segment. The node information of the "from" and
+	 * "to" attributes must already be in the dataset.
+	 * @param e		The line segment element to parse.
+	 * @param data	The dataset to obtain the node information from.
+	 * @return The parsed line segment.
+	 * @throws JDOMException In case of parsing errors.
+	 */
+	private LineSegment parseLineSegment(Element e, DataSet data) throws JDOMException {
+		long startId = Long.parseLong(e.getAttributeValue("from"));
+		long endId = Long.parseLong(e.getAttributeValue("to"));
+		
+		Node start = null, end = null;
+		for (Node n : data.nodes) {
+			if (n.id == startId)
+				start = n;
+			if (n.id == endId)
+				end = n;
+		}
+		if (start == null || end == null)
+			throw new JDOMException("The 'from' or 'to' object has not been transfered before.");
+		LineSegment ls = new LineSegment(start, end);
+		parseCommon(ls, e);
+		return ls;
+	}
+
+	/**
+	 * Parse and read a track from the element.
+	 *
+	 * @param e		The element that contain the track.
+	 * @param data	The DataSet to get segment information from.
+	 * @return 		The parsed track.
+	 * @throws JDOMException In case of a parsing error.
+	 */
+	private Track parseTrack(Element e, DataSet data) throws JDOMException {
+		Track track = new Track();
+		parseCommon(track, e);
+		for (Object o : e.getChildren("segment")) {
+			Element child = (Element)o;
+			long id = Long.parseLong(child.getAttributeValue("uid"));
+			LineSegment ls = findLineSegment(data.pendingLineSegments, id);
+			if (ls != null) {
+				track.segments.add(ls);
+				data.pendingLineSegments.remove(ls);
+				continue;
+			}
+			for (Track t : data.tracks) {
+				ls = findLineSegment(t.segments, id);
+				if (ls != null) {
+					track.segments.add(ls);
+					break;
+				}
+			}
+		}
+		return track;
+	}
+	
+	/**
+	 * Search for a segment in a collection by comparing the id.
+	 */
+	private LineSegment findLineSegment(Collection<LineSegment> segments, long id) {
+		for (LineSegment ls : segments)
+			if (ls.id == id)
+				return ls;
+		return null;
+	}
+	
+	/**
+	 * Adds the node to allNodes if it is not already listed. Does respect the
+	 * preference setting "mergeNodes". Return the node in the list that correspond
+	 * to the node in the list (either the new added or the old found).
+	 * 
+	 * If reading raw gps data, mergeNodes are always on (To save memory. You
+	 * can't edit raw gps nodes anyway.)
+	 * 
+	 * @param data The DataSet to add the node to.
+	 * @param node The node that should be added.
+	 * @return Either the parameter node or the old node found in the dataset. 
+	 */
+	private Node addNode(DataSet data, Node node) {
+		if (Main.pref.mergeNodes)
+			for (Node n : data.nodes)
+				if (node.coor.equalsLatLon(n.coor))
+					return n;
+		data.nodes.add(node);
+		return node;
+	}
+}
Index: src/org/openstreetmap/josm/io/OsmServerReader.java
===================================================================
--- src/org/openstreetmap/josm/io/OsmServerReader.java	(revision 25)
+++ src/org/openstreetmap/josm/io/OsmServerReader.java	(revision 27)
@@ -83,5 +83,5 @@
 		if (r == null)
 			return null;
-		return new GpxReader(r).parse();
+		return new OsmReader(r).parse();
 	}
 
Index: src/org/openstreetmap/josm/io/OsmWriter.java
===================================================================
--- src/org/openstreetmap/josm/io/OsmWriter.java	(revision 25)
+++ src/org/openstreetmap/josm/io/OsmWriter.java	(revision 27)
@@ -87,5 +87,5 @@
 		addProperties(e, t, properties);
 		for (LineSegment ls : t.segments)
-			e.getChildren().add(new Element("segment").setAttribute("id", ""+ls.id));
+			e.getChildren().add(new Element("segment").setAttribute("uid", ""+ls.id));
 		return e;
 	}
@@ -110,6 +110,6 @@
 		Element e = new Element("segment");
 		addProperties(e, ls, properties);
-		e.setAttribute("start", ""+ls.start.id);
-		e.setAttribute("end", ""+ls.end.id);
+		e.setAttribute("from", ""+ls.start.id);
+		e.setAttribute("to", ""+ls.end.id);
 		return e;
 	}
@@ -123,5 +123,5 @@
 		if (key.id == 0)
 			key.id = generateId();
-		e.setAttribute("id", ""+key.id);
+		e.setAttribute("uid", ""+key.id);
 		e.setAttribute("object", ""+osm.id);
 		e.setAttribute("key", key.name);
@@ -136,5 +136,5 @@
 		if (osm.id == 0)
 			osm.id = generateId();
-		e.setAttribute("id", ""+osm.id);
+		e.setAttribute("uid", ""+osm.id);
 		if (osm.keys != null)
 			for (Entry<Key, String> entry : osm.keys.entrySet())
