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
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.
*/
class OrgXmlpullStaxParser(val p: XmlPullParser, 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 = eventType
check(t == StaxEventType.StartElement || t == StaxEventType.EndElement) { "Not at StartElement/EndElement: $t" }
return QName(p.namespace, p.name)
}
override fun getAttributeName(index: Int): QName {
checkStartElement()
return QName(p.getAttributeNamespace(index), p.getAttributeName(index))
}
private fun checkStartElement() {
val t = 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() {
}
companion object {
private val types = listOf(StaxEventType.StartDocument, StaxEventType.EndDocument,
StaxEventType.StartElement, StaxEventType.EndElement, StaxEventType.Characters,
StaxEventType.CData, StaxEventType.EntityReference, StaxEventType.Space, StaxEventType.ProcessingInstruction,
StaxEventType.Comment, StaxEventType.DTD)
fun create(`in`: InputStream, systemId: String? = null): StaxParser {
val factory = 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 = factory.newPullParser()
parser.setInput(`in`, null)
return EntityExpandingStaxParser(OrgXmlpullStaxParser(parser, systemId))
}
}
}