mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2024-11-26 00:02:06 +01:00
4133eb175c
Introducing Smack's own XmlPullParser interface which tries to stay as compatible as possible to XPP3. The interface is used to either wrap StAX's XMLStreamReader if Smack is used on Java SE, and XPP3's XmlPullParser if Smack is used on on Android. Fixes SMACK-591. Also introduce JUnit 5 and non-strict javadoc projects.
75 lines
2.5 KiB
Markdown
75 lines
2.5 KiB
Markdown
Smack Providers
|
|
===============
|
|
|
|
Providers are responsible for parsing the XMPP XML stream into new Java objects.
|
|
|
|
Provider Design
|
|
---------------
|
|
|
|
Assume you want to parse the following stanza extension element
|
|
|
|
```xml
|
|
<myExtension attrFoo='fourthyTwo'>
|
|
<myElement>Foo is greater then Bar</myElement>
|
|
<myInfo alpha='true' delta='-1337'/>
|
|
</myExtension>
|
|
```
|
|
|
|
then the related provider would look like this
|
|
|
|
```java
|
|
public MyExtension parse(XmlPullParser parser, int initialDepth) {
|
|
MyElement myElement = null;
|
|
MyInfo myInfo = null;
|
|
String attrFoo = parser.getAttributeValue("", "attrFoo");
|
|
|
|
// Main parsing loop, use a loop label instead of "boolean done"
|
|
outerloop: while(true) {
|
|
// Make sure to have already parse all attributes of the outermost element,
|
|
// i.e. 'attrFoo' of 'myExtension' in this example. Then advance the parser
|
|
XmlPullParser.Event event = parser.next();
|
|
|
|
// Use switch/case of int instead of a if/else-if cascade
|
|
switch (event) {
|
|
case START_ELEMENT:
|
|
// Determine the name of the element which start tag we are seeing
|
|
String name = parser.getName();
|
|
// We can use switch/case of Strings since Java7, make use of its advantages
|
|
// and collect the values of the sub elements. If the sub elements are more
|
|
// complex then those of this example, consider creating extra *private static*
|
|
// parsing methods for them.
|
|
switch(name) {
|
|
case "myElement":
|
|
// You should only use XmlPullParser.nextText() when the element is
|
|
// required to have a text.
|
|
myElement = new MyElement(parser.nextText());
|
|
break;
|
|
case "myInfo";
|
|
// Use ParserUtils to parse Java primitives
|
|
boolenan alpha = ParserUtils.getBooleanAttribute(parser, "alpha");
|
|
int delta = ParserUtils.getIntegerAttribute(parser, "delta");
|
|
myInfo = new MyInfo(alpha, delta);
|
|
break;
|
|
}
|
|
break;
|
|
case END_ELEMENT:
|
|
// The abort condition with the break labeled loop statement
|
|
if (parser.getDepth() == initialDepth) {
|
|
break outerloop;
|
|
}
|
|
break;
|
|
default:
|
|
// Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Create the actual class at the very end, design the classes as immutable as possible
|
|
return new MyExtension(attrFoo, myElement, myInfo);
|
|
}
|
|
```
|
|
|
|
Common Pitfalls
|
|
---------------
|
|
|
|
Use a `long` instead of `int` when the XML schema says `xs:unsignedInt`, because Java's `int` range is to small for this XML numeric data type.
|