Index: src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(revision 5681)
+++ src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(working copy)
@@ -804,20 +804,6 @@
             dialog.showDialog();
             if (dialog.getValue() != 1) return false;
         }
-
-        ConflictCollection conflicts = getConflicts();
-        if (conflicts != null && !conflicts.isEmpty()) {
-            ExtendedDialog dialog = new ExtendedDialog(
-                    Main.parent,
-                    /* I18N: Display title of the window showing conflicts */
-                    tr("Conflicts"),
-                    new String[] {tr("Reject Conflicts and Save"), tr("Cancel")}
-            );
-            dialog.setContent(tr("There are unresolved conflicts. Conflicts will not be saved and handled as if you rejected all. Continue?"));
-            dialog.setButtonIcons(new String[] {"save.png", "cancel.png"});
-            dialog.showDialog();
-            if (dialog.getValue() != 1) return false;
-        }
         return true;
     }
     
Index: src/org/openstreetmap/josm/io/OsmReader.java
===================================================================
--- src/org/openstreetmap/josm/io/OsmReader.java	(revision 5681)
+++ src/org/openstreetmap/josm/io/OsmReader.java	(working copy)
@@ -18,12 +18,15 @@
 import javax.xml.stream.XMLStreamReader;
 
 import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.conflict.Conflict;
+import org.openstreetmap.josm.data.conflict.ConflictCollection;
 import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.osm.Changeset;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.DataSource;
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.NodeData;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
 import org.openstreetmap.josm.data.osm.PrimitiveData;
 import org.openstreetmap.josm.data.osm.Relation;
@@ -131,7 +134,8 @@
                 if (parser.getLocalName().equals("bounds")) {
                     parseBounds(generator);
                 } else if (parser.getLocalName().equals("node")) {
-                    parseNode();
+                    Node n = parseNode(false);
+                    externalIdMap.put(n.getPrimitiveId(), n);
                 } else if (parser.getLocalName().equals("way")) {
                     parseWay();
                 } else if (parser.getLocalName().equals("relation")) {
@@ -175,7 +179,16 @@
         jumpToEnd();
     }
 
-    protected Node parseNode() throws XMLStreamException {
+    /**
+     * Parse a node.
+     * 
+     * @param isConflict True, if the node participates in a conflict with
+     * role "their". False, if it is a regular node, that will be included
+     * in the DataSet.
+     * @return the parsed node
+     * @throws XMLStreamException
+     */
+    protected Node parseNode(boolean isConflict) throws XMLStreamException {
         NodeData nd = new NodeData();
         String lat = parser.getAttributeValue(null, "lat");
         String lon = parser.getAttributeValue(null, "lon");
@@ -186,12 +199,13 @@
         Node n = new Node(nd.getId(), nd.getVersion());
         n.setVisible(nd.isVisible());
         n.load(nd);
-        externalIdMap.put(nd.getPrimitiveId(), n);
         while (true) {
             int event = parser.next();
             if (event == XMLStreamConstants.START_ELEMENT) {
                 if (parser.getLocalName().equals("tag")) {
                     parseTag(n);
+                } else if (!isConflict && parser.getLocalName().equals("conflict")) {
+                    parseNodeConflict(n);
                 } else {
                     parseUnknown();
                 }
@@ -200,6 +214,22 @@
         }
     }
 
+    protected void parseNodeConflict(Node my) throws XMLStreamException {
+        Node their = null;
+        while (true) {
+            int event = parser.next();
+            if (event == XMLStreamConstants.START_ELEMENT) {
+                if (parser.getLocalName().equals("node")) {
+                    their = parseNode(true);
+                    conflicts.add(new Conflict(my, their));
+                } else {
+                    parseUnknown();
+                }
+            } else if (event == XMLStreamConstants.END_ELEMENT)
+                return;
+        }
+    }
+
     protected Way parseWay() throws XMLStreamException {
         WayData wd = new WayData();
         readCommon(wd);
@@ -348,7 +378,7 @@
         while (true) {
             int event = parser.next();
             if (event == XMLStreamConstants.START_ELEMENT) {
-                parseUnknown(false); /* no more warning for inner elements */
+                parseUnknown(false); /* no more warnings for inner elements */
             } else if (event == XMLStreamConstants.END_ELEMENT)
                 return;
         }
@@ -556,7 +586,7 @@
         }
     }
 
-    protected DataSet doParseDataSet(InputStream source, ProgressMonitor progressMonitor) throws IllegalDataException {
+    public DataSet parse(InputStream source, ProgressMonitor progressMonitor) throws IllegalDataException {
         if (progressMonitor == null) {
             progressMonitor = NullProgressMonitor.INSTANCE;
         }
@@ -616,6 +646,11 @@
      * @throws IllegalArgumentException thrown if source is null
      */
     public static DataSet parseDataSet(InputStream source, ProgressMonitor progressMonitor) throws IllegalDataException {
-        return new OsmReader().doParseDataSet(source, progressMonitor);
+        return new OsmReader().parse(source, progressMonitor);
     }
+
+    public ConflictCollection getConflicts() {
+        return conflicts;
+    }
+
 }
Index: src/org/openstreetmap/josm/io/OsmWriter.java
===================================================================
--- src/org/openstreetmap/josm/io/OsmWriter.java	(revision 5681)
+++ src/org/openstreetmap/josm/io/OsmWriter.java	(working copy)
@@ -11,6 +11,8 @@
 import java.util.List;
 import java.util.Map.Entry;
 
+import org.openstreetmap.josm.data.conflict.Conflict;
+import org.openstreetmap.josm.data.conflict.ConflictCollection;
 import org.openstreetmap.josm.data.coor.CoordinateFormat;
 import org.openstreetmap.josm.data.osm.Changeset;
 import org.openstreetmap.josm.data.osm.DataSet;
@@ -42,6 +44,7 @@
     private boolean isOsmChange;
     private String version;
     private Changeset changeset;
+    private ConflictCollection conflicts;
 
     /**
      * Do not call this directly. Use OsmWriterFactory instead.
@@ -52,10 +55,26 @@
         this.version = (version == null ? DEFAULT_API_VERSION : version);
     }
 
-    public void setWithBody(boolean wb) {
-        this.withBody = wb;
+    /**
+     * Set to false, if you want to skip the element body.
+     *
+     * If set to false, node coordinates, way nodes and relation members are
+     * omitted in the output.
+     *
+     * @param withBody false, if body should be skipped
+     */
+    public void setWithBody(boolean withBody) {
+        this.withBody = withBody;
     }
 
+    /**
+     * Set to true, if a .osmChange file is written.
+     *
+     * For upload of changes to the server, not all attributes that are
+     * normally written to a .osm file are needed.
+     *
+     * @param isOsmChange true, if a .osmChange file is written
+     */
     public void setIsOsmChange(boolean isOsmChange) {
         this.isOsmChange = isOsmChange;
     }
@@ -100,6 +119,7 @@
     public void writeLayer(OsmDataLayer layer) {
         header(!layer.isUploadDiscouraged());
         writeDataSources(layer.data);
+        conflicts = layer.getConflicts();
         writeContent(layer.data);
         footer();
     }
@@ -123,6 +143,8 @@
     }
 
     protected boolean shouldWrite(OsmPrimitive osm) {
+        // FIXME: the following condition should be equivalent:
+        // !osm.isNew() || !osm.isDeleted();
         return !osm.isNewOrUndeleted() || !osm.isDeleted();
     }
 
@@ -133,7 +155,7 @@
                     + s.bounds.getMin().lon()+"' maxlat='"
                     + s.bounds.getMax().lat()+"' maxlon='"
                     + s.bounds.getMax().lon()
-                    +"' origin='"+XmlWriter.encode(s.origin)+"' />");
+                    +"' origin='"+XmlWriter.encode(s.origin)+"'/>");
         }
     }
 
@@ -144,10 +166,46 @@
         if (!withBody) {
             out.println("/>");
         } else {
+            boolean hasInnerElements = false;
             if (n.getCoor() != null) {
                 out.print(" lat='"+n.getCoor().lat()+"' lon='"+n.getCoor().lon()+"'");
             }
-            addTags(n, "node", true);
+            if (n.hasKeys()) {
+                out.println(">");
+                hasInnerElements = true;
+                addTags(n, "    ");
+            }
+            Conflict c = conflicts.getConflictForMy(n);
+            if (c != null) {
+                IPrimitive th = c.getTheir();
+                if (th instanceof INode) {
+                    INode nConflict = (INode) th;
+                    if (!hasInnerElements) {
+                        out.println(">");
+                    }
+                    out.println("    <conflict>");
+                    // FIXME: add c.isMyDeleted and c.mergedMap
+                    out.print("    ");
+                    addCommon(th, "node");
+                    if (nConflict.getCoor() != null) {
+                        out.print(" lat='"+nConflict.getCoor().lat()+"' lon='"+nConflict.getCoor().lon()+"'");
+                    }
+                    if (nConflict.hasKeys()) {
+                        out.println(">");
+                        addTags(nConflict, "        ");
+                        out.println("      </node>");
+                    } else {
+                        out.println("/>");
+                    }
+                    out.println("    </conflict>");
+                    hasInnerElements = true;
+                }
+            }
+            if (hasInnerElements) {
+                out.println("  </node>");
+            } else {
+                out.println("/>");
+            }
         }
     }
 
@@ -216,6 +274,15 @@
         }
     };
 
+    protected void addTags(Tagged osm, String inset) {
+        List<Entry<String, String>> entries = new ArrayList<Entry<String,String>>(osm.getKeys().entrySet());
+        Collections.sort(entries, byKeyComparator);
+        for (Entry<String, String> e : entries) {
+            out.println(inset + "<tag k='"+ XmlWriter.encode(e.getKey()) +
+                    "' v='"+XmlWriter.encode(e.getValue())+ "'/>");
+        }
+    }
+
     protected void addTags(Tagged osm, String tagname, boolean tagOpen) {
         if (osm.hasKeys()) {
             if (tagOpen) {
Index: src/org/openstreetmap/josm/io/OsmImporter.java
===================================================================
--- src/org/openstreetmap/josm/io/OsmImporter.java	(revision 5681)
+++ src/org/openstreetmap/josm/io/OsmImporter.java	(working copy)
@@ -87,19 +87,17 @@
      * associatedFile can be null if the stream does not come from a file.
      */
     public OsmImporterData loadLayer(InputStream in, final File associatedFile, final String layerName, ProgressMonitor progressMonitor) throws IllegalDataException {
-        final DataSet dataSet = parseDataSet(in, progressMonitor);
+        OsmReader reader = new OsmReader();
+        DataSet dataSet = reader.parse(in, progressMonitor);
         if (dataSet == null) {
             throw new IllegalDataException(tr("Invalid dataset"));
         }
         OsmDataLayer layer = createLayer(dataSet, associatedFile, layerName);
+        layer.getConflicts().add(reader.getConflicts());
         Runnable postLayerTask = createPostLayerTask(dataSet, associatedFile, layerName, layer);
         return new OsmImporterData(layer, postLayerTask);
     }
 
-    protected DataSet parseDataSet(InputStream in, ProgressMonitor progressMonitor) throws IllegalDataException {
-        return OsmReader.parseDataSet(in, progressMonitor);
-    }
-
     protected OsmDataLayer createLayer(final DataSet dataSet, final File associatedFile, final String layerName) {
         return new OsmDataLayer(dataSet, layerName, associatedFile);
     }
Index: src/org/openstreetmap/josm/io/OsmChangeReader.java
===================================================================
--- src/org/openstreetmap/josm/io/OsmChangeReader.java	(revision 5681)
+++ src/org/openstreetmap/josm/io/OsmChangeReader.java	(working copy)
@@ -65,7 +65,7 @@
             if (event == XMLStreamConstants.START_ELEMENT) {
                 OsmPrimitive p = null;
                 if (parser.getLocalName().equals("node")) {
-                    p = parseNode();
+                    p = parseNode(false);
                 } else if (parser.getLocalName().equals("way")) {
                     p = parseWay();
                 } else if (parser.getLocalName().equals("relation")) {
@@ -97,6 +97,6 @@
      * @throws IllegalArgumentException thrown if source is null
      */
     public static DataSet parseDataSet(InputStream source, ProgressMonitor progressMonitor) throws IllegalDataException {
-        return new OsmChangeReader().doParseDataSet(source, progressMonitor);
+        return new OsmChangeReader().parse(source, progressMonitor);
     }
 }
Index: src/org/openstreetmap/josm/io/AbstractReader.java
===================================================================
--- src/org/openstreetmap/josm/io/AbstractReader.java	(revision 5681)
+++ src/org/openstreetmap/josm/io/AbstractReader.java	(working copy)
@@ -9,6 +9,7 @@
 import java.util.List;
 import java.util.Map;
 
+import org.openstreetmap.josm.data.conflict.ConflictCollection;
 import org.openstreetmap.josm.data.osm.Changeset;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.Node;
@@ -33,6 +34,8 @@
      */
     protected DataSet ds = new DataSet();
 
+    protected ConflictCollection conflicts = new ConflictCollection();
+
     protected Changeset uploadChangeset;
 
     /** the map from external ids to read OsmPrimitives. External ids are
@@ -189,6 +192,15 @@
             }
         }
     }
+
+    protected void processConflictsAfterParsing() {
+        // add conflict primitives with role "their" to a dummy dataset,
+        // because each primitive needs a parent dataset.
+        DataSet theirDataSet = new DataSet();
+        for (OsmPrimitive their : conflicts.getTheirConflictParties()) {
+            theirDataSet.addPrimitive(their);
+        }
+    }
     
     protected final void prepareDataSet() throws IllegalDataException {
         try {
Index: src/org/openstreetmap/josm/data/conflict/Conflict.java
===================================================================
--- src/org/openstreetmap/josm/data/conflict/Conflict.java	(revision 5681)
+++ src/org/openstreetmap/josm/data/conflict/Conflict.java	(working copy)
@@ -3,6 +3,7 @@
 
 import java.util.Map;
 
+import org.openstreetmap.josm.data.osm.IPrimitive;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.PrimitiveId;
 
@@ -45,7 +46,7 @@
         return their;
     }
 
-    public boolean isMatchingMy(OsmPrimitive my) {
+    public boolean isMatchingMy(IPrimitive my) {
         return this.my == my;
     }
 
Index: src/org/openstreetmap/josm/data/conflict/ConflictCollection.java
===================================================================
--- src/org/openstreetmap/josm/data/conflict/ConflictCollection.java	(revision 5681)
+++ src/org/openstreetmap/josm/data/conflict/ConflictCollection.java	(working copy)
@@ -11,6 +11,7 @@
 import java.util.Set;
 import java.util.concurrent.CopyOnWriteArrayList;
 
+import org.openstreetmap.josm.data.osm.IPrimitive;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
 
@@ -151,7 +152,7 @@
      * @return the conflict for the {@link OsmPrimitive} <code>my</code>, null
      * if no such conflict exists.
      */
-    public Conflict<?> getConflictForMy(OsmPrimitive my) {
+    public Conflict<?> getConflictForMy(IPrimitive my) {
         for(Conflict<?> c : conflicts) {
             if (c.isMatchingMy(my))
                 return c;
