Change summary
src/main/java/eu/siacs/conversations/xml/Element.java | 33 ++++++++++-
src/main/java/eu/siacs/conversations/xml/Node.java | 3 +
src/main/java/eu/siacs/conversations/xml/TextNode.java | 6 ++
src/main/java/eu/siacs/conversations/xml/XmlReader.java | 15 ++---
4 files changed, 45 insertions(+), 12 deletions(-)
Detailed changes
@@ -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<String, String> 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<String, String> getSerializableAttributes(Hashtable<String, String> ns) {
+ final var result = new Hashtable<String, String>();
+ 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;
@@ -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<String, String> ns);
}
@@ -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<String, String> ns) {
+ return toString();
+ }
}
@@ -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);
}