All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.gitlab.mvysny.konsumexml.stax.OrgXmlpullStaxParser.kt Maven / Gradle / Ivy

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))
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy