improved the DOM API a little with a few more helper methods and syntax sugar
This commit is contained in:
@@ -1,11 +1,57 @@
|
||||
package std.dom
|
||||
|
||||
import std.*
|
||||
import std.util.*
|
||||
import java.util.*
|
||||
import org.w3c.dom.*
|
||||
|
||||
|
||||
// Properties
|
||||
|
||||
val Document?.rootElement : Element?
|
||||
get() = if (this != null) this.getDocumentElement() else null
|
||||
|
||||
|
||||
var Node.text : String
|
||||
get() {
|
||||
if (this is Element) {
|
||||
return this.text
|
||||
} else {
|
||||
return this.getNodeValue() ?: ""
|
||||
}
|
||||
}
|
||||
set(value) {
|
||||
if (this is Element) {
|
||||
this.text = value
|
||||
} else {
|
||||
this.setNodeValue(value)
|
||||
}
|
||||
}
|
||||
|
||||
var Element.text : String
|
||||
get() {
|
||||
val buffer = StringBuilder()
|
||||
val nodeList = this.getChildNodes()
|
||||
if (nodeList != null) {
|
||||
var i = 0
|
||||
val size = nodeList.getLength()
|
||||
while (i < size) {
|
||||
val node = nodeList.item(i)
|
||||
if (node != null) {
|
||||
if (node.getNodeType() == Node.TEXT_NODE || node.getNodeType() == Node.CDATA_SECTION_NODE) {
|
||||
buffer.append(node.getNodeValue())
|
||||
}
|
||||
}
|
||||
i++
|
||||
}
|
||||
}
|
||||
return buffer.toString().sure()
|
||||
}
|
||||
set(value) {
|
||||
// lets remove all the previous text nodes first
|
||||
this.setAttribute("id", value)
|
||||
}
|
||||
|
||||
var Element.id : String
|
||||
get() = this.getAttribute("id")?: ""
|
||||
set(value) {
|
||||
@@ -25,6 +71,104 @@ set(value) {
|
||||
this.setAttribute("class", value)
|
||||
}
|
||||
|
||||
|
||||
// Helper methods
|
||||
|
||||
inline fun Element?.children(): List<Node> {
|
||||
return this?.getChildNodes().toList()
|
||||
}
|
||||
|
||||
inline fun Element?.elementsByTagName(name: String?): List<Element> {
|
||||
return this?.getElementsByTagName(name).toElementList()
|
||||
}
|
||||
|
||||
inline fun Element?.elementsByTagNameNS(namespaceUri: String?, localName: String?): List<Element> {
|
||||
return this?.getElementsByTagNameNS(namespaceUri, localName).toElementList()
|
||||
}
|
||||
|
||||
inline fun Document?.elementsByTagName(name: String?): List<Element> {
|
||||
return this?.getElementsByTagName(name).toElementList()
|
||||
}
|
||||
|
||||
inline fun Document?.elementsByTagNameNS(namespaceUri: String?, localName: String?): List<Element> {
|
||||
return this?.getElementsByTagNameNS(namespaceUri, localName).toElementList()
|
||||
}
|
||||
|
||||
val NodeList?.head : Node?
|
||||
get() = if (this != null && this.getLength() > 0) this.item(0) else null
|
||||
|
||||
val NodeList?.first : Node?
|
||||
get() = this.head
|
||||
|
||||
val NodeList?.tail : Node?
|
||||
get() {
|
||||
if (this == null) {
|
||||
return null
|
||||
} else {
|
||||
val s = this.getLength()
|
||||
return if (s > 0) this.item(s - 1) else null
|
||||
}
|
||||
}
|
||||
|
||||
val NodeList?.last : Node?
|
||||
get() = this.tail
|
||||
|
||||
|
||||
inline fun NodeList?.toList(): List<Node> {
|
||||
return if (this == null) {
|
||||
Collections.EMPTY_LIST as List<Node>
|
||||
}
|
||||
else {
|
||||
NodeListAsList(this)
|
||||
}
|
||||
}
|
||||
|
||||
inline fun NodeList?.toElementList(): List<Element> {
|
||||
return if (this == null) {
|
||||
Collections.EMPTY_LIST as List<Element>
|
||||
}
|
||||
else {
|
||||
ElementListAsList(this)
|
||||
}
|
||||
}
|
||||
|
||||
fun NodeList?.toXmlString(xmlDeclaration: Boolean = false): String {
|
||||
return if (this == null)
|
||||
"" else {
|
||||
this.toList().toXmlString(xmlDeclaration)
|
||||
}
|
||||
}
|
||||
|
||||
class NodeListAsList(val nodeList: NodeList): AbstractList<Node>() {
|
||||
override fun get(index: Int): Node {
|
||||
val node = nodeList.item(index)
|
||||
if (node == null) {
|
||||
throw IndexOutOfBoundsException("NodeList does not contain a node at index: " + index)
|
||||
} else {
|
||||
return node
|
||||
}
|
||||
}
|
||||
|
||||
override fun size(): Int = nodeList.getLength()
|
||||
}
|
||||
|
||||
class ElementListAsList(val nodeList: NodeList): AbstractList<Element>() {
|
||||
override fun get(index: Int): Element {
|
||||
val node = nodeList.item(index)
|
||||
if (node is Element) {
|
||||
return node
|
||||
} else {
|
||||
if (node == null) {
|
||||
throw IndexOutOfBoundsException("NodeList does not contain a node at index: " + index)
|
||||
} else {
|
||||
throw IllegalArgumentException("Node is not an Element as expected but is $node")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun size(): Int = nodeList.getLength()
|
||||
|
||||
}
|
||||
// Syntax sugar
|
||||
|
||||
inline fun Node.plus(child: Node?): Node {
|
||||
|
||||
@@ -14,6 +14,9 @@ import javax.xml.transform.stream.StreamResult
|
||||
|
||||
import java.io.StringWriter
|
||||
import javax.xml.transform.OutputKeys
|
||||
import java.lang.Iterable
|
||||
import java.util.List
|
||||
import java.util.Collection
|
||||
|
||||
fun createDocument(builder: DocumentBuilder): Document {
|
||||
return builder.newDocument().sure()
|
||||
@@ -36,6 +39,17 @@ fun Node.toXmlString(xmlDeclaration: Boolean = this is Document): String {
|
||||
return nodeToXmlString(this, xmlDeclaration)
|
||||
}
|
||||
|
||||
fun java.lang.Iterable<Node>.toXmlString(xmlDeclaration: Boolean = false): String {
|
||||
// TODO this should work...
|
||||
// return this.map<Node,String>{it.toXmlString()}.join("")
|
||||
val builder = StringBuilder()
|
||||
for (n in this) {
|
||||
builder.append(n.toXmlString(xmlDeclaration))
|
||||
}
|
||||
return builder.toString().sure()
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
fun Document.toXmlString(xmlDeclaration: Boolean = true): String {
|
||||
return nodeToXmlString(this, xmlDeclaration)
|
||||
|
||||
@@ -2,12 +2,13 @@ package test.dom
|
||||
|
||||
import std.*
|
||||
import std.dom.*
|
||||
import std.util.*
|
||||
import stdhack.test.*
|
||||
import org.w3c.dom.*
|
||||
|
||||
class DomBuilderTest() : TestSupport() {
|
||||
|
||||
fun testBuildDocumnet() {
|
||||
fun testBuildDocument() {
|
||||
var doc = createDocument()
|
||||
|
||||
doc.addElement("foo") {
|
||||
@@ -19,11 +20,24 @@ class DomBuilderTest() : TestSupport() {
|
||||
addElement("grandChild") {
|
||||
cssClass = "tiny"
|
||||
addText("Hello World!")
|
||||
// TODO support neater syntax sugar for adding text?
|
||||
// += "Hello World!"
|
||||
// TODO support neater syntax sugar for adding text?
|
||||
// += "Hello World!"
|
||||
}
|
||||
}
|
||||
}
|
||||
println("builder document: ${doc.toXmlString()}")
|
||||
|
||||
|
||||
val grandChild = doc.elementsByTagName("grandChild").first
|
||||
if (grandChild != null) {
|
||||
println("got element ${grandChild.toXmlString()} with text '${grandChild.text}`")
|
||||
assertEquals("Hello World!", grandChild.text)
|
||||
} else {
|
||||
fail("Not an Element $grandChild")
|
||||
}
|
||||
val children = doc.rootElement.children()
|
||||
val xml = children.toXmlString()
|
||||
println("root element has children: ${xml}")
|
||||
assertEquals(1, children.size())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user