StaxXmlPullParser.java
- /**
- *
- * Copyright 2019 Florian Schmaus
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.jivesoftware.smack.xml.stax;
- import java.io.IOException;
- import javax.xml.XMLConstants;
- import javax.xml.namespace.NamespaceContext;
- import javax.xml.namespace.QName;
- import javax.xml.stream.Location;
- import javax.xml.stream.XMLStreamConstants;
- import javax.xml.stream.XMLStreamException;
- import javax.xml.stream.XMLStreamReader;
- import org.jivesoftware.smack.xml.XmlPullParser;
- import org.jivesoftware.smack.xml.XmlPullParserException;
- public final class StaxXmlPullParser implements XmlPullParser {
- private final XMLStreamReader xmlStreamReader;
- private int depth;
- StaxXmlPullParser(XMLStreamReader xmlStreamReader) {
- this.xmlStreamReader = xmlStreamReader;
- }
- @Override
- public Object getProperty(String name) {
- return xmlStreamReader.getProperty(name);
- }
- @Override
- public String getInputEncoding() {
- return xmlStreamReader.getEncoding();
- }
- @Override
- public int getNamespaceCount() {
- return xmlStreamReader.getNamespaceCount();
- }
- @Override
- public String getNamespacePrefix(int pos) {
- return xmlStreamReader.getNamespacePrefix(pos);
- }
- @Override
- public String getNamespaceUri(int pos) {
- return xmlStreamReader.getNamespaceURI(pos);
- }
- @Override
- public String getNamespace(String prefix) {
- if (prefix == null) {
- prefix = XMLConstants.DEFAULT_NS_PREFIX;
- }
- NamespaceContext namespaceContext = xmlStreamReader.getNamespaceContext();
- return namespaceContext.getNamespaceURI(prefix);
- }
- @Override
- public String getNamespace() {
- String prefix = getPrefix();
- return getNamespace(prefix);
- }
- @Override
- public int getDepth() {
- return depth;
- }
- @Override
- public String getPositionDescription() {
- Location location = xmlStreamReader.getLocation();
- return location.toString();
- }
- @Override
- public int getLineNumber() {
- Location location = xmlStreamReader.getLocation();
- return location.getLineNumber();
- }
- @Override
- public int getColumnNumber() {
- Location location = xmlStreamReader.getLocation();
- return location.getColumnNumber();
- }
- @Override
- public boolean isWhiteSpace() {
- return xmlStreamReader.isWhiteSpace();
- }
- @Override
- public String getText() {
- return xmlStreamReader.getText();
- }
- @Override
- public String getName() {
- QName qname = getQName();
- return qname.getLocalPart();
- }
- @Override
- public QName getQName() {
- return xmlStreamReader.getName();
- }
- @Override
- public String getPrefix() {
- return xmlStreamReader.getPrefix();
- }
- @Override
- public int getAttributeCount() {
- return xmlStreamReader.getAttributeCount();
- }
- @Override
- public String getAttributeNamespace(int index) {
- return xmlStreamReader.getAttributeNamespace(index);
- }
- @Override
- public String getAttributeName(int index) {
- QName qname = getAttributeQName(index);
- if (qname == null) {
- return null;
- }
- return qname.getLocalPart();
- }
- @Override
- public QName getAttributeQName(int index) {
- return xmlStreamReader.getAttributeName(index);
- }
- @Override
- public String getAttributePrefix(int index) {
- return xmlStreamReader.getAttributePrefix(index);
- }
- @Override
- public String getAttributeType(int index) {
- return xmlStreamReader.getAttributeType(index);
- }
- @Override
- public String getAttributeValue(int index) {
- return xmlStreamReader.getAttributeValue(index);
- }
- @Override
- public String getAttributeValue(String namespace, String name) {
- String namespaceURI = namespace;
- String localName = name;
- return xmlStreamReader.getAttributeValue(namespaceURI, localName);
- }
- @Override
- public Event getEventType() {
- int staxEventInt = xmlStreamReader.getEventType();
- return staxEventIntegerToEvent(staxEventInt);
- }
- private boolean delayedDepthDecrement;
- @Override
- public Event next() throws XmlPullParserException {
- preNextEvent();
- int staxEventInt;
- try {
- staxEventInt = xmlStreamReader.next();
- } catch (XMLStreamException e) {
- throw new XmlPullParserException(e);
- }
- Event event = staxEventIntegerToEvent(staxEventInt);
- switch (event) {
- case START_ELEMENT:
- depth++;
- break;
- case END_ELEMENT:
- delayedDepthDecrement = true;
- break;
- default:
- // Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
- break;
- }
- return event;
- }
- @Override
- public String nextText() throws IOException, XmlPullParserException {
- final String nextText;
- try {
- nextText = xmlStreamReader.getElementText();
- } catch (XMLStreamException e) {
- throw new XmlPullParserException(e);
- }
- // XMLStreamReader.getElementText() will forward to the next END_ELEMENT, hence we need to set
- // delayedDepthDecrement to true.
- delayedDepthDecrement = true;
- return nextText;
- }
- @Override
- public TagEvent nextTag() throws IOException, XmlPullParserException {
- preNextEvent();
- int staxEventInt;
- try {
- staxEventInt = xmlStreamReader.nextTag();
- } catch (XMLStreamException e) {
- throw new XmlPullParserException(e);
- }
- switch (staxEventInt) {
- case XMLStreamConstants.START_ELEMENT:
- depth++;
- return TagEvent.START_ELEMENT;
- case XMLStreamConstants.END_ELEMENT:
- delayedDepthDecrement = true;
- return TagEvent.END_ELEMENT;
- default:
- throw new AssertionError();
- }
- }
- private void preNextEvent() {
- if (delayedDepthDecrement) {
- depth--;
- delayedDepthDecrement = false;
- assert depth >= 0;
- }
- }
- private static Event staxEventIntegerToEvent(int staxEventInt) {
- switch (staxEventInt) {
- case XMLStreamConstants.START_ELEMENT:
- return Event.START_ELEMENT;
- case XMLStreamConstants.END_ELEMENT:
- return Event.END_ELEMENT;
- case XMLStreamConstants.PROCESSING_INSTRUCTION:
- return Event.PROCESSING_INSTRUCTION;
- case XMLStreamConstants.CHARACTERS:
- return Event.TEXT_CHARACTERS;
- case XMLStreamConstants.COMMENT:
- return Event.COMMENT;
- case XMLStreamConstants.SPACE:
- return Event.IGNORABLE_WHITESPACE;
- case XMLStreamConstants.START_DOCUMENT:
- return Event.START_DOCUMENT;
- case XMLStreamConstants.END_DOCUMENT:
- return Event.END_DOCUMENT;
- case XMLStreamConstants.ENTITY_REFERENCE:
- return Event.ENTITY_REFERENCE;
- case XMLStreamConstants.ATTRIBUTE:
- return Event.OTHER;
- case XMLStreamConstants.DTD:
- return Event.OTHER;
- case XMLStreamConstants.CDATA:
- return Event.OTHER;
- case XMLStreamConstants.NAMESPACE:
- return Event.OTHER;
- case XMLStreamConstants.NOTATION_DECLARATION:
- return Event.OTHER;
- case XMLStreamConstants.ENTITY_DECLARATION:
- return Event.OTHER;
- default:
- throw new IllegalArgumentException("Unknown Stax event integer: " + staxEventInt);
- }
- }
- @Override
- public boolean supportsRoundtrip() {
- // TODO: Is there a StAX parser implementation which does support roundtrip?
- return false;
- }
- }