Skip to content
Snippets Groups Projects
Commit d40027fc authored by Kaj Koivunen's avatar Kaj Koivunen :coffee:
Browse files

XMLParserin optimointi

parent 35554b3f
No related branches found
No related tags found
No related merge requests found
package guru.kake.ronove
import java.io.FileInputStream
import javax.xml.namespace.QName
import javax.xml.stream.XMLEventReader
import javax.xml.stream.XMLInputFactory
import javax.xml.stream.events.XMLEvent
......
......@@ -18,20 +18,31 @@ class XMLParser private constructor(path: String) {
/**
* Parse an XML-file using an event-based interface
* @param path path to file
* @param loop lambda to execute on each XML event
* @param init lambda to execute on each XML event
*/
fun parse(path: String, loop: XMLParser.() -> Unit) = XMLParser(path).init(loop)
fun parse(path: String, init: XMLParser.() -> Unit) = XMLParser(path).init(init)
}
private val factory: XMLInputFactory = XMLInputFactory.newInstance()
private val reader: XMLEventReader = factory.createXMLEventReader(FileInputStream(path))
private var event: XMLEvent? = null
private val elements: MutableMap<String, Element> = mutableMapOf()
private fun init(loop: XMLParser.() -> Unit) {
private fun init(init: XMLParser.() -> Unit) {
@Suppress("UNUSED_EXPRESSION") // IntelliJ IDEA bug: https://youtrack.jetbrains.com/issue/KT-21282
init()
while (reader.hasNext()) {
event = reader.nextEvent()
@Suppress("UNUSED_EXPRESSION") // IntelliJ IDEA bug: https://youtrack.jetbrains.com/issue/KT-21282
loop()
parse(reader.nextEvent())
}
}
private fun parse(event: XMLEvent) {
when {
event.isStartElement -> {
elements[event.asStartElement().name.localPart.toString()]?.parseStart(event)
}
event.isEndElement -> {
elements[event.asEndElement().name.localPart.toString()]?.parseEnd()
}
}
}
......@@ -40,17 +51,29 @@ class XMLParser private constructor(path: String) {
* @param name Element name
* @param f code to execute on elements matching name
*/
fun element(name: String, f: Element.() -> Unit) = Element(name, reader, event!!).f()
fun element(name: String, f: Element.() -> Unit) {
elements[name] = Element(reader).also { it.f() }
}
@DSL
inner class Element(private val name: String, private val reader: XMLEventReader, private val event: XMLEvent) {
inner class Element(private val reader: XMLEventReader) {
private var startFunc: (() -> Unit)? = null
private var endFunc: (() -> Unit)? = null
private var event: XMLEvent? = null
internal fun parseStart(event: XMLEvent) {
this.event = event
startFunc?.invoke()
}
internal fun parseEnd() { endFunc?.invoke() }
/**
* Specify code to execute when encountering a starting tag of the specified element
* @param f code to execute
*/
fun start(f: StartElement.() -> Unit) {
if (event.isStartElement && event.asStartElement().name.localPart.toString() == name)
StartElement(reader, event.asStartElement()).f()
fun start(f: () -> Unit) {
startFunc = f
}
/**
......@@ -58,27 +81,27 @@ class XMLParser private constructor(path: String) {
* @param f code to execute
*/
fun end(f: () -> Unit) {
if (event.isEndElement && event.asEndElement().name.localPart.toString() == name)
f()
endFunc = f
}
@DSL
inner class StartElement(private val reader: XMLEventReader, private val event: javax.xml.stream.events.StartElement) {
/**
* Get the content of the current element
*/
fun content(): String? {
return try {
reader.peek().asCharacters().data
} catch (e: ClassCastException) {
null
}
}
/**
* Get the content of the current element
* @return content of current tag or null
*/
/**
*
*/
fun attribute(attr: String): String? = event.getAttributeByName(QName(attr))?.value
fun content(): String? {
return try {
reader.peek().asCharacters().data
} catch (e: ClassCastException) {
null
}
}
/**
* Get attribute of current element if it exists or null. Only works within a start element.
* @param attribute attribute name
* @return value of attribute or null
*/
fun attribute(attribute: String): String? = event!!.asStartElement().getAttributeByName(QName(attribute))?.value
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment