com.gitlab.mvysny.konsumexml.stax.OrgXmlpullStaxParser.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of konsume-xml Show documentation
Show all versions of konsume-xml Show documentation
Konsume-XML: A simple functional XML parser with no annotations
The newest version!
package com.gitlab.mvysny.konsumexml.stax
import org.xmlpull.v1.XmlPullParser
import org.xmlpull.v1.XmlPullParserFactory
import java.io.InputStream
import javax.xml.namespace.QName
/**
* This parser uses the [XmlPullParser] which is present in Android 8+ and also in the `org.ogce:xpp3:1.1.6` jar file;
* however the API is not present in JavaSE by default.
*/
public class OrgXmlpullStaxParser(public val p: XmlPullParser, public val systemId: String? = null) : StaxParser {
override val eventType: StaxEventType
get() = types[p.eventType]
override val location: Location
get() = Location(p.lineNumber, p.columnNumber + 1, -1, null, systemId)
override val elementName: QName
get() {
val t: StaxEventType = eventType
check(t == StaxEventType.StartElement || t == StaxEventType.EndElement) { "Not at StartElement/EndElement: $t" }
return QName(p.namespace, p.name, p.prefix ?: "")
}
override fun getAttributeName(index: Int): QName {
checkStartElement()
return QName(p.getAttributeNamespace(index), p.getAttributeName(index), p.getAttributePrefix(index) ?: "")
}
private fun checkStartElement() {
val t: StaxEventType = eventType
check(t == StaxEventType.StartElement) { "Attributes are only accessible when on StartElement: $t" }
}
override val attributeCount: Int
get() {
checkStartElement()
return p.attributeCount
}
override fun getAttributeValue(namespaceURI: String, localName: String): String? {
checkStartElement()
return p.getAttributeValue(namespaceURI, localName)
}
override val text: String
get() = p.text
override fun next() {
if (!hasNext()) {
throw NoSuchElementException()
}
p.nextToken()
}
override fun hasNext(): Boolean = eventType != StaxEventType.EndDocument
override fun close() {
// nothing to clean up.
}
public companion object {
private val types: List = listOf(StaxEventType.StartDocument, StaxEventType.EndDocument,
StaxEventType.StartElement, StaxEventType.EndElement, StaxEventType.Characters,
StaxEventType.CData, StaxEventType.EntityReference, StaxEventType.Space, StaxEventType.ProcessingInstruction,
StaxEventType.Comment, StaxEventType.DTD)
/**
* Starts parsing given [stream] using the org.xmlpull stax parser implementation.
*/
public fun create(stream: InputStream, systemId: String? = null): StaxParser {
val factory: XmlPullParserFactory = XmlPullParserFactory.newInstance().apply {
isNamespaceAware = true
isValidating = false
// this fails with org.xmlpull.v1.XmlPullParserException: unsupported feature http://xmlpull.org/v1/doc/features.html#expand-entity-ref;
//setFeature("http://xmlpull.org/v1/doc/features.html#expand-entity-ref", true)
// therefore we need to expand the entities manually
}
val parser: XmlPullParser = factory.newPullParser()
parser.setInput(stream, null)
return EntityExpandingStaxParser(OrgXmlpullStaxParser(parser, systemId))
}
}
}