diff --git a/src/main/java/eu/siacs/conversations/xml/Element.java b/src/main/java/eu/siacs/conversations/xml/Element.java index ff660505a766935d4c5e84c3504c720976dc0d90..bb505539a72e64cda8261fae43228ed77a3386c2 100644 --- a/src/main/java/eu/siacs/conversations/xml/Element.java +++ b/src/main/java/eu/siacs/conversations/xml/Element.java @@ -4,6 +4,7 @@ import androidx.annotation.NonNull; import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.google.common.primitives.Ints; import java.util.ArrayList; @@ -179,17 +180,24 @@ public class Element implements Node { } public String toString() { + return toString(ImmutableMap.of()); + } + + public String toString(final ImmutableMap parentNS) { + final var mutns = new Hashtable<>(parentNS); + final var attr = getSerializableAttributes(mutns); final StringBuilder elementOutput = new StringBuilder(); if (childNodes.size() == 0) { Tag emptyTag = Tag.empty(name); - emptyTag.setAttributes(this.attributes); + emptyTag.setAttributes(attr); elementOutput.append(emptyTag.toString()); } else { + final var ns = ImmutableMap.copyOf(mutns); Tag startTag = Tag.start(name); - startTag.setAttributes(this.attributes); + startTag.setAttributes(attr); elementOutput.append(startTag); for (Node child : ImmutableList.copyOf(childNodes)) { - elementOutput.append(child.toString()); + elementOutput.append(child.toString(ns)); } Tag endTag = Tag.end(name); elementOutput.append(endTag); @@ -197,6 +205,25 @@ public class Element implements Node { return elementOutput.toString(); } + protected Hashtable getSerializableAttributes(Hashtable ns) { + final var result = new Hashtable(); + for (final var attr : attributes.entrySet()) { + if (attr.getKey().charAt(0) == '{') { + final var uriIdx = attr.getKey().indexOf('}'); + final var uri = attr.getKey().substring(1, uriIdx - 1); + if (!ns.containsKey(uri)) { + result.put("ns" + ns.size() + ":xmlns", uri); + ns.put(uri, "ns" + ns.size()); + } + result.put(ns.get(uri) + ":" + attr.getKey().substring(uriIdx + 1), attr.getValue()); + } else { + result.put(attr.getKey(), attr.getValue()); + } + } + + return result; + } + public Element removeAttribute(String name) { this.attributes.remove(name); return this; diff --git a/src/main/java/eu/siacs/conversations/xml/Node.java b/src/main/java/eu/siacs/conversations/xml/Node.java index dbe18d252ddc981f9b0d6c3e41d6f97fc211c8b0..d06904c27411af9eaca3462b24454f6f5495ab2e 100644 --- a/src/main/java/eu/siacs/conversations/xml/Node.java +++ b/src/main/java/eu/siacs/conversations/xml/Node.java @@ -1,5 +1,8 @@ package eu.siacs.conversations.xml; +import com.google.common.collect.ImmutableMap; + public interface Node { public String getContent(); + public String toString(final ImmutableMap ns); } diff --git a/src/main/java/eu/siacs/conversations/xml/TextNode.java b/src/main/java/eu/siacs/conversations/xml/TextNode.java index edbc1d312a6e282470d56f2ba279cd054b9ee52c..4c73002a53b182a061e6f85748fc9213076613eb 100644 --- a/src/main/java/eu/siacs/conversations/xml/TextNode.java +++ b/src/main/java/eu/siacs/conversations/xml/TextNode.java @@ -1,5 +1,7 @@ package eu.siacs.conversations.xml; +import com.google.common.collect.ImmutableMap; + import eu.siacs.conversations.utils.XmlHelper; public class TextNode implements Node { @@ -17,4 +19,8 @@ public class TextNode implements Node { public String toString() { return XmlHelper.encodeEntities(content); } + + public String toString(final ImmutableMap ns) { + return toString(); + } } diff --git a/src/main/java/eu/siacs/conversations/xml/XmlReader.java b/src/main/java/eu/siacs/conversations/xml/XmlReader.java index 4c78745a85baffd127aa619dba70f6f03e942546..aee7d7819aeaecd7064f83c83ee6ac5aed5f5f25 100644 --- a/src/main/java/eu/siacs/conversations/xml/XmlReader.java +++ b/src/main/java/eu/siacs/conversations/xml/XmlReader.java @@ -61,21 +61,18 @@ public class XmlReader implements Closeable { Tag tag = Tag.start(parser.getName()); final String xmlns = parser.getNamespace(); for (int i = 0; i < parser.getAttributeCount(); ++i) { - final String prefix = parser.getAttributePrefix(i); + final var prefix = parser.getAttributePrefix(i); + final var ns = parser.getAttributeNamespace(i); String name; - if (prefix != null && !prefix.isEmpty()) { - name = prefix+":"+parser.getAttributeName(i); + if ("xml".equals(prefix)) { + name = "xml:" + parser.getAttributeName(i); + } else if (ns != null && !ns.isEmpty()) { + name = "{" + ns + "}" + parser.getAttributeName(i); } else { name = parser.getAttributeName(i); } tag.setAttribute(name,parser.getAttributeValue(i)); } - int nsStart = parser.getNamespaceCount(parser.getDepth()-1); - int nsEnd = parser.getNamespaceCount(parser.getDepth()); - for (int i = nsStart; i < nsEnd; i++) { - final var prefix = parser.getNamespacePrefix(i); - tag.setAttribute("xmlns" + (prefix == null ? "" : ":" + prefix), parser.getNamespaceUri(i)); - } if (xmlns != null) { tag.setAttribute("xmlns", xmlns); }