Index: trunk/src/org/openstreetmap/josm/gui/tagging/TaggingPresetReader.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/tagging/TaggingPresetReader.java	(revision 6561)
+++ trunk/src/org/openstreetmap/josm/gui/tagging/TaggingPresetReader.java	(revision 6562)
@@ -17,4 +17,5 @@
 import java.util.List;
 import java.util.Map;
+import java.util.Stack;
 
 import javax.swing.JOptionPane;
@@ -92,6 +93,7 @@
         List<TaggingPresetItems.PresetListEntry> listEntries = new LinkedList<TaggingPresetItems.PresetListEntry>();
         final Map<String, List<Object>> byId = new HashMap<String, List<Object>>();
-        String lastId = null;
-        Iterator<Object> lastIdIterator = null;
+        final Stack<String> lastIds = new Stack<String>();
+        /** lastIdIterators contains non empty iterators of items to be handled before obtaining the next item from the XML parser */
+        final Stack<Iterator<Object>> lastIdIterators = new Stack<Iterator<Object>>();
 
         if (validate) {
@@ -100,29 +102,32 @@
             parser.start(in);
         }
-        while (parser.hasNext()) {
+        while (parser.hasNext() || !lastIdIterators.isEmpty()) {
             final Object o;
-            if (lastIdIterator != null && lastIdIterator.hasNext()) {
-                // obtain elements from lastIdIterator with higher priority
-                o = lastIdIterator.next();
+            if (!lastIdIterators.isEmpty()) {
+                // obtain elements from lastIdIterators with higher priority
+                o = lastIdIterators.peek().next();
+                if (!lastIdIterators.peek().hasNext()) {
+                    // remove iterator is is empty
+                    lastIdIterators.pop();
+                }
             } else {
                 o = parser.next();
             }
             if (o instanceof Chunk) {
-                if (((Chunk) o).id.equals(lastId)) {
-                    // reset last id on end of object, don't process further
-                    lastId = null;
+                if (!lastIds.isEmpty() && ((Chunk) o).id.equals(lastIds.peek())) {
+                    // pop last id on end of object, don't process further
+                    lastIds.pop();
                     ((Chunk) o).id = null;
                     continue;
-                } else if (lastId == null) {
+                } else {
                     // if preset item contains an id, store a mapping for later usage
-                    lastId = ((Chunk) o).id;
+                    String lastId = ((Chunk) o).id;
+                    lastIds.push(lastId);
                     byId.put(lastId, new ArrayList<Object>());
                     continue;
-                } else {
-                    throw new IllegalStateException("Cannot deal with nested id objects (lastId was expected to be null)");
-                }
-            } else if (lastId != null) {
+                }
+            } else if (!lastIds.isEmpty()) {
                 // add object to mapping for later usage
-                byId.get(lastId).add(o);
+                byId.get(lastIds.peek()).add(o);
                 continue;
             }
@@ -134,5 +139,5 @@
                     throw new SAXException(tr("Reference {0} is being used before it was defined", ref));
                 }
-                lastIdIterator = byId.get(ref).iterator();
+                lastIdIterators.push(byId.get(ref).iterator());
                 continue;
             }
