Skip to content

Instantly share code, notes, and snippets.

@agumonkey
Last active March 3, 2019 11:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save agumonkey/86c7efe6cc0f05ec9c42d744eaec792a to your computer and use it in GitHub Desktop.
Save agumonkey/86c7efe6cc0f05ec9c42d744eaec792a to your computer and use it in GitHub Desktop.
xml to sax to tree in kotlin
package x
import java.util.Stack
import java.io.File
import javax.xml.parsers.*
import org.xml.sax.*
import org.xml.sax.helpers.*
class Node(val l:String, val q:String, val u:String, val a:Map<String,String>) {
val children:MutableList<Node> = mutableListOf<Node>()
constructor(q:String):this("<localName>",q,"<uri>",mapOf<String,String>())
override fun toString():String { return "<$u::$q:$l $a, ${children.size}>" }
fun addChild(n:Node) { children.add(n) }
}
fun Node.linearize():List<Node> {
return listOf(this) + this.children.map(Node::linearize).flatten()
}
fun Attributes.mapped():Map<String,String> {
return (0..this.getLength()-1)
.map({ i -> this.getLocalName(i) to this.getValue(i) })
.toMap()
}
class Xml(val pred:(String)->Boolean):DefaultHandler() {
val matches:MutableList<Pair<String,Map<String,String>>> = mutableListOf()
val stack:Stack<Node> = Stack<Node>().apply { push(Node("root")) }
override fun startElement(u:String, l:String, q:String, a:Attributes) {
val m = a.mapped()
if (this.pred(q)) { matches.add(q to m) }
stack.push(Node(l, q, u, m)) // shift?
}
override fun endElement(uri:String, localName:String, qName:String) {
val n = stack.pop()
stack.peek().addChild(n) // reduce
}
override fun toString():String {
return "<Xml(${matches.size}) $matches>"
}
}
fun xml(source:String="gest.xml", tag:String="a"):Xml {
val handler = Xml({ s -> s == tag})
val parser = SAXParserFactory.newInstance().newSAXParser()
val file = File(source)
parser.parse(file, handler)
return handler
}
fun main(args: Array<String>) {
args.forEach { a ->
println()
println(a)
println("----")
xml(a).let { h -> h.stack.peek().linearize().forEach(::println) }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment