mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2024-12-23 04:57:58 +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 {
|
||||
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 {
|
||||
return getParserFor(new StringReader(stanza));
|
||||
}
|
||||
|
@ -144,6 +146,12 @@ public class PacketParserUtils {
|
|||
public static XmlPullParser newXmppParser() throws XmlPullParserException {
|
||||
XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -368,12 +376,14 @@ public class PacketParserUtils {
|
|||
* 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.
|
||||
* <p>
|
||||
* This method is able to parse the content with MX- and KXmlParser. In order to achieve
|
||||
* this some trade-off has to be make, because KXmlParser does not support xml-roundtrip (ie.
|
||||
* return a String on getText() on START_TAG and END_TAG). We are therefore required to work
|
||||
* around this limitation, which results in only partial support for XML namespaces ("xmlns"):
|
||||
* Only the outermost namespace of elements will be included in the resulting String, if
|
||||
* <code>fullNamespaces</code> is set to false.
|
||||
* This method is able to parse the content with MX- and KXmlParser. KXmlParser does not support
|
||||
* xml-roundtrip. i.e. return a String on getText() on START_TAG and END_TAG. We check for the
|
||||
* XML_ROUNDTRIP feature. If it's not found we are required to work around this limitation, which
|
||||
* results in only partial support for XML namespaces ("xmlns"): Only the outermost namespace of
|
||||
* elements will be included in the resulting String, if <code>fullNamespaces</code> is set to false.
|
||||
* </p>
|
||||
* <p>
|
||||
* In particular Android's XmlPullParser does not support XML_ROUNDTRIP.
|
||||
* </p>
|
||||
*
|
||||
* @param parser
|
||||
|
@ -384,6 +394,15 @@ public class PacketParserUtils {
|
|||
* @throws 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();
|
||||
int event = parser.getEventType();
|
||||
boolean isEmptyElement = false;
|
||||
|
@ -437,6 +456,24 @@ public class PacketParserUtils {
|
|||
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.
|
||||
*
|
||||
|
|
Loading…
Reference in a new issue