Index: /trunk/src/org/openstreetmap/josm/io/remotecontrol/AddTagsDialog.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/remotecontrol/AddTagsDialog.java	(revision 19570)
+++ /trunk/src/org/openstreetmap/josm/io/remotecontrol/AddTagsDialog.java	(revision 19571)
@@ -284,5 +284,5 @@
      */
     public static Map<String, String> parseUrlTagsToKeyValues(String urlSection) {
-        Map<String, String> tags = TextTagParser.readTagsByRegexp(urlSection, "\\|", "(.*?)=(.*?)", false);
+        Map<String, String> tags = TextTagParser.readTagsByRegexp(urlSection, "(?<!\\\\)\\|", "(.*?)=(.*?)", false, true);
         return tags == null ? Collections.emptyMap() : tags;
     }
Index: /trunk/src/org/openstreetmap/josm/tools/TextTagParser.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/tools/TextTagParser.java	(revision 19570)
+++ /trunk/src/org/openstreetmap/josm/tools/TextTagParser.java	(revision 19571)
@@ -47,13 +47,16 @@
      * @param tagRegex - each part is matched against this regex
      * @param unescapeTextInQuotes - if true, matched tag and value will be analyzed more thoroughly
+     * @param unescapePipe - if true, then replace all '\|' by '|' (issue #14490)
      * @return map of tags
+     * @since 19570 (parameter unescapePipe added)
      */
-    public static Map<String, String> readTagsByRegexp(String text, String splitRegex, String tagRegex, boolean unescapeTextInQuotes) {
-         String[] lines = text.split(splitRegex, -1);
-         Pattern p = Pattern.compile(tagRegex);
-         Map<String, String> tags = new LinkedHashMap<>();
-         String k;
-         String v;
-         for (String line: lines) {
+    public static Map<String, String> readTagsByRegexp(String text, String splitRegex, String tagRegex, 
+            boolean unescapeTextInQuotes, boolean unescapePipe) {
+        String[] lines = text.split(splitRegex, -1);
+        Pattern p = Pattern.compile(tagRegex);
+        Map<String, String> tags = new LinkedHashMap<>();
+        String k;
+        String v;
+        for (String line: lines) {
             if (line.trim().isEmpty()) continue; // skip empty lines
             Matcher m = p.matcher(line);
@@ -66,14 +69,18 @@
                      if (k == null || v == null) return null;
                  }
+                 if (unescapePipe) {
+                     k = k.replaceAll("\\\\\\|", "|");
+                     v = v.replaceAll("\\\\\\|", "|");
+                 }
                  tags.put(k, v);
             } else {
                 return null;
             }
-         }
-         if (!tags.isEmpty()) {
-            return tags;
-         } else {
-            return null;
-         }
+        }
+        if (!tags.isEmpty()) {
+           return tags;
+        } else {
+           return null;
+        }
     }
 
@@ -100,5 +107,5 @@
         // Format
         // tag1\tval1\ntag2\tval2\n
-        tags = readTagsByRegexp(buf, "[\\r\\n]+", ".*?([a-zA-Z0-9:_]+).*\\t(.*?)", false);
+        tags = readTagsByRegexp(buf, "[\\r\\n]+", ".*?([a-zA-Z0-9:_]+).*\\t(.*?)", false, false);
         // try "tag\tvalue\n" format
         if (tags != null) return tags;
@@ -109,5 +116,5 @@
         // a = "b=c" is OK
         // a = b=c  - this method of parsing fails intentionally
-        tags = readTagsByRegexp(buf, "[\\n\\t\\r]+", "(.*?)=(.*?)", true);
+        tags = readTagsByRegexp(buf, "[\\n\\t\\r]+", "(.*?)=(.*?)", true, false);
         // try format  t1=v1\n t2=v2\n ...
         if (tags != null) return tags;
@@ -119,5 +126,5 @@
             bufJson = bufJson.substring(1, bufJson.length()-1);
         tags = readTagsByRegexp(bufJson, "[\\s]*,[\\s]*",
-                "[\\s]*(\\\".*?[^\\\\]\\\")"+"[\\s]*:[\\s]*"+"(\\\".*?[^\\\\]\\\")[\\s]*", true);
+                "[\\s]*(\\\".*?[^\\\\]\\\")"+"[\\s]*:[\\s]*"+"(\\\".*?[^\\\\]\\\")[\\s]*", true, false);
         if (tags != null) return tags;
 
Index: /trunk/test/unit/org/openstreetmap/josm/io/remotecontrol/AddTagsDialogTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/io/remotecontrol/AddTagsDialogTest.java	(revision 19570)
+++ /trunk/test/unit/org/openstreetmap/josm/io/remotecontrol/AddTagsDialogTest.java	(revision 19571)
@@ -24,3 +24,51 @@
         assertEquals("Dresden Castle", strings.get("name:en"));
     }
+
+    /**
+     * Unit test for issue #14490 "Support for escaping pipe character in remote control addtags parameters"
+     * A single URL section (value of addtags=...) with a single escaped pipe sysmbol
+     */
+    @Test
+    void testParseUrlTagsToKeyValues_OneKeyValuePair_OneEscapedPipe() {
+        Map<String, String> strings = AddTagsDialog.parseUrlTagsToKeyValues("gtfs:route_id=de:mvv-muenchen:19-210\\|210");
+        assertEquals(1, strings.size());
+        assertEquals("de:mvv-muenchen:19-210|210", strings.get("gtfs:route_id"));
+    }
+
+    /**
+     * Unit test for issue #14490 "Support for escaping pipe character in remote control addtags parameters"
+     * A single URL section (value of addtags=...) with two escaped pipe sysmbols
+     */
+    @Test
+    void testParseUrlTagsToKeyValues_OneKeyValuePair_TwoEscapedPipe() {
+        Map<String, String> strings = AddTagsDialog.parseUrlTagsToKeyValues("gtfs:route_id=de:mvv-muenchen:19-210\\|210\\|RegionalBus:1179_3");
+        assertEquals(1, strings.size());
+        assertEquals("de:mvv-muenchen:19-210|210|RegionalBus:1179_3", strings.get("gtfs:route_id"));
+    }
+
+    /**
+     * Unit test for issue #14490 "Support for escaping pipe character in remote control addtags parameters"
+     * Two URL sections (values of addtags=...) with two escaped pipe sysmbols each
+     */
+    @Test
+    void testParseUrlTagsToKeyValues_TwoKeyValuePairs_FourEscapedPipe() {
+        Map<String, String> strings = AddTagsDialog.parseUrlTagsToKeyValues("gtfs:route_id=de:mvv-muenchen:19-210\\|210\\|"
+        + "RegionalBus:1179_3|gtfs:trip_id:sample=de:mvv-muenchen:19-210\\|210\\|RegionalBus:1179-1-1-H-0-We#3-320-333");
+        assertEquals(2, strings.size());
+        assertEquals("de:mvv-muenchen:19-210|210|RegionalBus:1179_3", strings.get("gtfs:route_id"));
+        assertEquals("de:mvv-muenchen:19-210|210|RegionalBus:1179-1-1-H-0-We#3-320-333", strings.get("gtfs:trip_id:sample"));
+    }
+
+    /**
+     * Unit test for issue #14490 "Support for escaping pipe character in remote control addtags parameters"
+     * Two URL sections (values of addtags=...) with four unescaped pipe sysmbols in the value parts
+     * Same as the test above, but without escapeing the pipe symbols
+     * This is how it worked before the patch, even if the pipe symbols would have been escaped
+     */
+    @Test
+    void testParseUrlTagsToKeyValues_PipeInValue_NoEscapedPipe() {
+        Map<String, String> strings = AddTagsDialog.parseUrlTagsToKeyValues("gtfs:route_id=de:mvv-muenchen:19-210|210|"
+        + "RegionalBus:1179_3|gtfs:trip_id:sample=de:mvv-muenchen:19-210|210|RegionalBus:1179-1-1-H-0-We#3-320-333");
+        assertEquals(0, strings.size());
+    }
 }
Index: /trunk/test/unit/org/openstreetmap/josm/tools/TextTagParserTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/tools/TextTagParserTest.java	(revision 19570)
+++ /trunk/test/unit/org/openstreetmap/josm/tools/TextTagParserTest.java	(revision 19571)
@@ -176,5 +176,5 @@
         List<String> expected = Arrays.asList("foo4", "foo3", "foo2", "foo1");
         ArrayList<String> actual = new ArrayList<>(TextTagParser.readTagsByRegexp(
-                "foo4=bar4 foo3=bar3 foo2=bar2 foo1=bar1", " ", "(.*?)=(.*?)", true).keySet());
+                "foo4=bar4 foo3=bar3 foo2=bar2 foo1=bar1", " ", "(.*?)=(.*?)", true, false).keySet());
         assertEquals(expected, actual);
     }
