13.05.2018
Read and parse XML with Kotlin
How do I read an XML or html file with Kotlin and examine its content? Here are some snippets of code how to read an XML or Html file with Kotlin and then examine the XML elements, their attributes and values. The following XML file is used as a sample file (items.xml):
<ItemSet> <Item type="T1" count="1">Value1</Item> <Item type="T1" count="2">Value2</Item> <Item type="T2" count="1">Value3</Item> <Item type="T2" count="1">Value4</Item> </ItemSet>
Read XML File
The following snippet reads the Xml file into a Document:
fun readXml(): Document { val xmlFile = File("./input/items.xml") val dbFactory = DocumentBuilderFactory.newInstance() val dBuilder = dbFactory.newDocumentBuilder() val xmlInput = InputSource(StringReader(xmlFile.readText())) val doc = dBuilder.parse(xmlInput) return doc }
getElementValuesByAttributeNameAndAttributeValue
The following code snippet shows how to read the value of the XML element based on an attribute and its attribute value.
/** * Create a list with all values where the attribute name is 'attributeName' and its value is 'attributeValue' * * Example: *- Value1
* Value 'Value1' is in the list if attributeName is 'type' and attributeValue is 'T1'. * */ fun getElementValuesByAttributeNameAndAttributeValue(doc: Document, attributeValue: String, attributeName: String): List<String> { val xpFactory = XPathFactory.newInstance() val xPath = xpFactory.newXPath() //- Value1
val xpath = "/ItemSet/Item[contains(@$attributeName, '$attributeValue')]" val itemsTypeT1 = xPath.evaluate(xpath, doc, XPathConstants.NODESET) as NodeList val itemList: MutableList<String> = ArrayList() for (i in 0..itemsTypeT1.length - 1) { itemList.add(itemsTypeT1.item(i).textContent) } return ArrayList(itemList) }
An xPath is created that stores all Item elements from the Document in a NodeList. At the same time, in the xPath, the attributeName
(type
) is used to filter all item elements that have the value as the value in the attributeValue
attribute T1
. If the function is called with the following parameters: getElementValuesByAttributeNameAndAttributeValue(doc, "T1", "type")
After the xPath has been evaluated with evaluate
, the values are read out in order and written to a new list. [Value1, Value2]
getAttributeValuesByAttributeNameAndAttributeValue
The following snippet shows how to filter the attribute values based on the attribute name and attribute value.
/** * * Create a list with all attribute values where the 'attributeName', 'attributeValue' and 'attributeValueName' match. * * *- Value1
* Value '1' is in the list if attributeName is 'type' and attributeValue is 'T1' and 'attributeValueName' is 'count'. * */ fun getAttributeValuesByAttributeNameAndAttributeValue(doc: Document, attributeValue: String, attributeName: String, attributeValueName: String): List<String> { val xpFactory = XPathFactory.newInstance() val xPath = xpFactory.newXPath() //- Value1
val xpath = "/ItemSet/Item[contains(@$attributeName, '$attributeValue')]" val itemsTypeT1 = xPath.evaluate(xpath, doc, XPathConstants.NODESET) as NodeList val itemList: MutableList<String> = ArrayList() for (i in 0..itemsTypeT1.length - 1) { val attributeValue = itemsTypeT1.item(i).attributes.getNamedItem(attributeValueName) val value = attributeValue.nodeValue itemList.add(attributeValue.nodeValue) } return ArrayList(itemList) }
An xPath is created that stores all Item elements from the Document in a NodeList. At the same time, in the xPath, the attributeName
(type
) is used to filter all item elements that have the value as the value in the attributeValue
attribute T1
. If the function is called with the following parameters: getAttributeValuesByAttributeNameAndAttributeValue(doc, "T1", "type", "count")
After the xPath has been evaluated with evaluate
, the values are read out in order and written to a new list. The result should be [1, 2]
.
examineElementAttributes
The following code snippet shows how to extract all attributes of an Xml element.
/** * * Create a list with all attributes of the element mithh the name 'elementName. * * Only the first elelemt of the doc is examined! * */ fun examineElementAttributes(doc: Document, elementName: String): List<String> { val xpFactory = XPathFactory.newInstance() val xPath = xpFactory.newXPath() val xpath = "/ItemSet/$elementName" val elementNodeList = xPath.evaluate(xpath, doc, XPathConstants.NODESET) as NodeList val firstElement = elementNodeList.item(0) val attributeList: MutableList<String> = ArrayList() for (i in 0..firstElement.attributes.length - 1) { val attribute = firstElement.attributes.item(i); attributeList.add(attribute.nodeName) println(attribute) } return ArrayList(attributeList) }
The xPath selects all elements by its name elementName
. After the xpath is evaluated the first element in the NodeList is examinded. All attributes are stored in a new List. The result should be [count, type]
if the function is called with the following parameters: examineElementAttributes(doc, "Item")
.
Please do not forget: This is not a perfect Kotlin code. These are code snippets that show how to work with Kotlin and Xml.