mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2024-11-26 16:22:06 +01:00
Support XML_ROUNDTRIP where possible
The approach to avoid XmlPullParser's XML_ROUNDTRIP feature prevents Smack from handling XML namespaces on e.g. PubSub payloads on platforms where support for XML_ROUNDTRIP would be available. We now check for this XmlPullParser feature and use it if it's available.
This commit is contained in:
parent
9a6d042652
commit
ed58abbee7
1 changed files with 43 additions and 6 deletions
|
@ -59,6 +59,8 @@ import org.xmlpull.v1.XmlPullParserFactory;
|
||||||
public class PacketParserUtils {
|
public class PacketParserUtils {
|
||||||
private static final Logger LOGGER = Logger.getLogger(PacketParserUtils.class.getName());
|
private static final Logger LOGGER = Logger.getLogger(PacketParserUtils.class.getName());
|
||||||
|
|
||||||
|
public static final String FEATURE_XML_ROUNDTRIP = "http://xmlpull.org/v1/doc/features.html#xml-roundtrip";
|
||||||
|
|
||||||
public static XmlPullParser getParserFor(String stanza) throws XmlPullParserException, IOException {
|
public static XmlPullParser getParserFor(String stanza) throws XmlPullParserException, IOException {
|
||||||
return getParserFor(new StringReader(stanza));
|
return getParserFor(new StringReader(stanza));
|
||||||
}
|
}
|
||||||
|
@ -144,6 +146,12 @@ public class PacketParserUtils {
|
||||||
public static XmlPullParser newXmppParser() throws XmlPullParserException {
|
public static XmlPullParser newXmppParser() throws XmlPullParserException {
|
||||||
XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
|
XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
|
||||||
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
|
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
|
||||||
|
try {
|
||||||
|
parser.setFeature(FEATURE_XML_ROUNDTRIP, true);
|
||||||
|
} catch (XmlPullParserException e) {
|
||||||
|
// Doesn't matter if FEATURE_XML_ROUNDTRIP isn't available
|
||||||
|
LOGGER.log(Level.FINEST, "XmlPullParser does not support XML_ROUNDTRIP", e);
|
||||||
|
}
|
||||||
return parser;
|
return parser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,12 +376,14 @@ public class PacketParserUtils {
|
||||||
* not nested ones, if <code>fullNamespaces</code> is false. If it is true, then namespaces of
|
* not nested ones, if <code>fullNamespaces</code> is false. If it is true, then namespaces of
|
||||||
* parent elements will be added to child elements that don't define a different namespace.
|
* parent elements will be added to child elements that don't define a different namespace.
|
||||||
* <p>
|
* <p>
|
||||||
* This method is able to parse the content with MX- and KXmlParser. In order to achieve
|
* This method is able to parse the content with MX- and KXmlParser. KXmlParser does not support
|
||||||
* this some trade-off has to be make, because KXmlParser does not support xml-roundtrip (ie.
|
* xml-roundtrip. i.e. return a String on getText() on START_TAG and END_TAG. We check for the
|
||||||
* return a String on getText() on START_TAG and END_TAG). We are therefore required to work
|
* XML_ROUNDTRIP feature. If it's not found we are required to work around this limitation, which
|
||||||
* around this limitation, which results in only partial support for XML namespaces ("xmlns"):
|
* results in only partial support for XML namespaces ("xmlns"): Only the outermost namespace of
|
||||||
* Only the outermost namespace of elements will be included in the resulting String, if
|
* elements will be included in the resulting String, if <code>fullNamespaces</code> is set to false.
|
||||||
* <code>fullNamespaces</code> is set to false.
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* In particular Android's XmlPullParser does not support XML_ROUNDTRIP.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param parser
|
* @param parser
|
||||||
|
@ -384,6 +394,15 @@ public class PacketParserUtils {
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public static CharSequence parseContentDepth(XmlPullParser parser, int depth, boolean fullNamespaces) throws XmlPullParserException, IOException {
|
public static CharSequence parseContentDepth(XmlPullParser parser, int depth, boolean fullNamespaces) throws XmlPullParserException, IOException {
|
||||||
|
if (parser.getFeature(FEATURE_XML_ROUNDTRIP)) {
|
||||||
|
return parseContentDepthWithRoundtrip(parser, depth, fullNamespaces);
|
||||||
|
} else {
|
||||||
|
return parseContentDepthWithoutRoundtrip(parser, depth, fullNamespaces);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CharSequence parseContentDepthWithoutRoundtrip(XmlPullParser parser, int depth,
|
||||||
|
boolean fullNamespaces) throws XmlPullParserException, IOException {
|
||||||
XmlStringBuilder xml = new XmlStringBuilder();
|
XmlStringBuilder xml = new XmlStringBuilder();
|
||||||
int event = parser.getEventType();
|
int event = parser.getEventType();
|
||||||
boolean isEmptyElement = false;
|
boolean isEmptyElement = false;
|
||||||
|
@ -437,6 +456,24 @@ public class PacketParserUtils {
|
||||||
return xml;
|
return xml;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static CharSequence parseContentDepthWithRoundtrip(XmlPullParser parser, int depth, boolean fullNamespaces)
|
||||||
|
throws XmlPullParserException, IOException {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
int event = parser.getEventType();
|
||||||
|
outerloop: while (true) {
|
||||||
|
// Only append the text if the parser is not on on an empty element' start tag. Empty elements are reported
|
||||||
|
// twice, so in order to prevent duplication we only add their text when we are on their end tag.
|
||||||
|
if (!(event == XmlPullParser.START_TAG && parser.isEmptyElementTag())) {
|
||||||
|
sb.append(parser.getText());
|
||||||
|
}
|
||||||
|
if (event == XmlPullParser.END_TAG && parser.getDepth() <= depth) {
|
||||||
|
break outerloop;
|
||||||
|
}
|
||||||
|
event = parser.next();
|
||||||
|
}
|
||||||
|
return sb;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses a presence packet.
|
* Parses a presence packet.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in a new issue