org.xmlpull.v1.util.XmlPullUtil Maven / Gradle / Ivy
/* -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- //------100-columns-wide------>|*/
// for license please see accompanying LICENSE.txt file (available also at http://www.xmlpull.org/)
package org.xmlpull.v1.util;
import java.io.IOException;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
/**
* Handy functions that combines XmlPull API into higher level functionality.
*
* @author Aleksander Slominski
* @author Naresh Bhatia
*/
public class XmlPullUtil {
public static final String XSI_NS = "http://www.w3.org/2001/XMLSchema-instance";
private XmlPullUtil() {}
/**
* Return value of attribute with given name and no namespace.
*/
public static String getAttributeValue(XmlPullParser pp, String name) {
return pp.getAttributeValue(XmlPullParser.NO_NAMESPACE, name);
}
/**
* Return PITarget from Processing Instruction (PI) as defined in
* XML 1.0 Section 2.6 Processing Instructions
* [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
*/
public static String getPITarget(XmlPullParser pp) throws IllegalStateException
{
int eventType;
try {
eventType = pp.getEventType();
} catch(XmlPullParserException ex) {
// should never happen ...
throw new IllegalStateException(
"could not determine parser state: "+ex+pp.getPositionDescription());
}
if( eventType != XmlPullParser.PROCESSING_INSTRUCTION ) {
throw new IllegalStateException(
"parser must be on processing instruction and not "
+XmlPullParser.TYPES[ eventType ]+pp.getPositionDescription());
}
final String PI = pp.getText();
for (int i = 0; i < PI.length(); i++)
{
if( isS(PI.charAt(i)) ) {
// assert i > 0
return PI.substring(0,i);
}
}
return PI;
}
/**
* Return everything past PITarget and S from Processing Instruction (PI) as defined in
* XML 1.0 Section 2.6 Processing Instructions
* [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
*
* NOTE: if there is no PI data it returns empty string.
*/
public static String getPIData(XmlPullParser pp) throws IllegalStateException
{
int eventType;
try {
eventType = pp.getEventType();
} catch(XmlPullParserException ex) {
// should never happen ...
throw new IllegalStateException(
"could not determine parser state: "+ex+pp.getPositionDescription());
}
if( eventType != XmlPullParser.PROCESSING_INSTRUCTION ) {
throw new IllegalStateException(
"parser must be on processing instruction and not "
+XmlPullParser.TYPES[ eventType ]+pp.getPositionDescription());
}
final String PI = pp.getText();
int pos = -1;
for (int i = 0; i < PI.length(); i++)
{
if( isS(PI.charAt(i)) ) {
pos = i;
} else if(pos > 0) {
return PI.substring(i);
}
}
return "";
}
/**
* Return true if chacters is S as defined in XML 1.0
* S ::= (#x20 | #x9 | #xD | #xA)+
*/
private static boolean isS(char ch) {
return (ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t');
}
/**
* Skip sub tree that is currently porser positioned on.
*
NOTE: parser must be on START_TAG and when funtion returns
* parser will be positioned on corresponding END_TAG
*/
public static void skipSubTree(XmlPullParser pp)
throws XmlPullParserException, IOException
{
pp.require(XmlPullParser.START_TAG, null, null);
int level = 1;
while(level > 0) {
int eventType = pp.next();
if(eventType == XmlPullParser.END_TAG) {
--level;
} else if(eventType == XmlPullParser.START_TAG) {
++level;
}
}
}
/**
* call parser nextTag() and check that it is START_TAG, throw exception if not.
*/
public static void nextStartTag(XmlPullParser pp)
throws XmlPullParserException, IOException
{
if(pp.nextTag() != XmlPullParser.START_TAG) {
throw new XmlPullParserException(
"expected START_TAG and not "+pp.getPositionDescription());
}
}
/**
* combine nextTag(); pp.require(pp.START_TAG, null, name);
*/
public static void nextStartTag(XmlPullParser pp, String name)
throws XmlPullParserException, IOException
{
pp.nextTag();
pp.require(XmlPullParser.START_TAG, null, name);
}
/**
* combine nextTag(); pp.require(pp.START_TAG, namespace, name);
*/
public static void nextStartTag(XmlPullParser pp, String namespace, String name)
throws XmlPullParserException, IOException
{
pp.nextTag();
pp.require(XmlPullParser.START_TAG, namespace, name);
}
/**
* combine nextTag(); pp.require(pp.END_TAG, namespace, name);
*/
public static void nextEndTag(XmlPullParser pp, String namespace, String name)
throws XmlPullParserException, IOException
{
pp.nextTag();
pp.require(XmlPullParser.END_TAG, namespace, name);
}
/**
* Read text content of element ith given namespace and name
* (use null namespace do indicate that nemspace should not be checked)
*/
public static String nextText(XmlPullParser pp, String namespace, String name)
throws IOException, XmlPullParserException
{
if(name == null) {
throw new XmlPullParserException("name for element can not be null");
}
pp.require(XmlPullParser.START_TAG, namespace, name);
return pp.nextText();
}
/**
* Read attribute value and return it or throw exception if
* current element does not have such attribute.
*/
public static String getRequiredAttributeValue(XmlPullParser pp, String namespace, String name)
throws IOException, XmlPullParserException
{
String value = pp.getAttributeValue(namespace, name);
if (value == null) {
throw new XmlPullParserException("required attribute "+name+" is not present");
} else {
return value;
}
}
/**
* Call parser nextTag() and check that it is END_TAG, throw exception if not.
*/
public static void nextEndTag(XmlPullParser pp) throws XmlPullParserException, IOException
{
if(pp.nextTag() != XmlPullParser.END_TAG) {
throw new XmlPullParserException(
"expected END_TAG and not"+pp.getPositionDescription());
}
}
/**
* Tests if the current event is of the given type and if the namespace and name match.
* null will match any namespace and any name. If the test passes a true is returned
* otherwise a false is returned.
*/
public static boolean matches(XmlPullParser pp, int type, String namespace, String name)
throws XmlPullParserException
{
boolean matches = type == pp.getEventType()
&& (namespace == null || namespace.equals (pp.getNamespace()))
&& (name == null || name.equals (pp.getName ()));
return matches;
}
/**
* Writes a simple element such as johndoe . The namespace
* and elementText are allowed to be null. If elementText is null, an xsi:nil="true"
* will be added as an attribute.
*/
public static void writeSimpleElement(XmlSerializer serializer,
String namespace,
String elementName,
String elementText)
throws IOException, XmlPullParserException {
if (elementName == null) {
throw new XmlPullParserException("name for element can not be null");
}
serializer.startTag(namespace, elementName);
if (elementText == null) {
serializer.attribute(XSI_NS, "nil", "true");
} else {
serializer.text(elementText);
}
serializer.endTag(namespace, elementName);
}
}