de.lessvoid.xml.xpp3.XmlParser Maven / Gradle / Ivy
package de.lessvoid.xml.xpp3;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import javax.annotation.Nonnull;
import javax.annotation.WillNotClose;
import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* XmlParser is a helper/wrapper around XPP3.
*
* @author void
*/
public class XmlParser {
/**
* logger.
*/
@Nonnull
private static final Logger log = Logger.getLogger(XmlParser.class.getName());
/**
* the parser we should use.
*/
@Nonnull
private final XmlPullParser xpp;
/**
* Create a new XmlParser using the given XmlPullParser.
*
* @param xppParam the XmlPullParser to use
*/
public XmlParser(@Nonnull final XmlPullParser xppParam) {
this.xpp = xppParam;
}
/**
* Load xml.
*
* @param inputStream InputStream to read from
* @throws Exception exception
*/
public void read(@Nonnull @WillNotClose final InputStream inputStream) throws Exception {
xpp.setInput(inputStream, null);
}
/**
* Required element.
*
* @param tag required tag
* @param xmlElement handler
* @throws Exception exception
*/
public void required(@Nonnull final String tag, @Nonnull final XmlProcessor xmlElement) throws Exception {
if (isEndTag()) {
throw new Exception("found end tag but required tag [" + tag + "]");
}
if (!matchesTag(tag)) {
throw new Exception("Expected tag [" + tag + "] but was [" + xpp.getName() + "]");
}
processElement(xmlElement);
nextTag();
}
/**
* Optional element.
*
* @param tag required tag
* @param xmlElement handler
* @throws Exception exception
*/
public void optional(@Nonnull final String tag, @Nonnull final XmlProcessor xmlElement) throws Exception {
if (isEndTag()) {
return;
}
if (!matchesTag(tag)) {
return;
}
processElement(xmlElement);
nextTag();
}
/**
* Zero or more element.
*
* @param tag element tag
* @param xmlElement handler
* @throws Exception exception
*/
public void zeroOrMore(@Nonnull final String tag, @Nonnull final XmlProcessor xmlElement) throws Exception {
if (isEndTag()) {
return;
}
if (!matchesTag(tag)) {
return;
}
processElement(xmlElement);
nextTag();
zeroOrMore(tag, xmlElement);
}
/**
* check if the current tag is an end tag.
*
* @return true on end tag reached and false otherwise
* @throws Exception exception
*/
private boolean isEndTag() throws Exception {
return XmlPullParser.END_TAG == xpp.getEventType();
}
/**
* SubstitionGroup Support.
*
* @param substGroup SubstitutionGroup
* @throws Exception exception
*/
public void zeroOrMore(@Nonnull final SubstitutionGroup substGroup) throws Exception {
if (isEndTag()) {
return;
}
XmlProcessor element = substGroup.matches(xpp.getName());
if (element == null) {
return;
}
processElement(element);
nextTag();
zeroOrMore(substGroup);
}
/**
* One or more element.
*
* @param tag element tag
* @param xmlElement handler
* @throws Exception exception
*/
public void oneOrMore(@Nonnull final String tag, @Nonnull final XmlProcessor xmlElement) throws Exception {
if (isEndTag()) {
throw new Exception("End tag reached but was expecting [" + tag + "]");
}
if (!matchesTag(tag)) {
throw new Exception("Expected tag [" + tag + "] but was [" + xpp.getName() + "]");
}
processElement(xmlElement);
nextTag();
zeroOrMore(tag, xmlElement);
}
/**
* Process the element.
*
* @param xmlElement xmlElement
* @throws Exception exception
*/
private void processElement(@Nonnull final XmlProcessor xmlElement) throws Exception {
log.fine("process element: " + xmlElement.getClass().getName());
try {
xmlElement.process(this, new Attributes(xpp));
} catch (Exception ex) {
if (!(ex instanceof XmlPullParserException)) {
throw new XmlPullParserException("Error parsing document.", xpp, ex);
} else {
throw ex;
}
}
}
/**
* Does the current tag matches the given one?
*
* @param tag tag to check
* @return true if tags match and false otherwise
*/
private boolean matchesTag(@Nonnull final String tag) {
return tag.equals(xpp.getName());
}
/**
* next start or end tag.
*
* @throws Exception exception
*/
public void nextTag() throws Exception {
if (xpp.getEventType() == XmlPullParser.END_DOCUMENT) {
return;
}
int eventType = xpp.next();
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.END_TAG) {
if (log.isLoggable(Level.FINE)) {
indent();
log.fine(indent() + "END <" + xpp.getName() + ">");
}
return;
} else if (eventType == XmlPullParser.START_TAG) {
if (log.isLoggable(Level.FINE)) {
log.fine(indent() + "START <" + xpp.getName() + ">");
}
return;
}
eventType = xpp.next();
}
}
/**
* indent current xpp depth level.
*
* @return string of whitespace of xpp depth level length
*/
@Nonnull
private String indent() {
StringBuilder b = new StringBuilder();
for (int i = 0; i < xpp.getDepth(); i++) {
b.append(' ');
}
return b.toString();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy