Обзор XML парсеров

  • XPath
  • JAXB (Java Architecture for XML Binding, DOM – Document Object Model)
  • StAX (Streaming API for XML, SAX – Simple API for XML)

Инструменты

fun reader() = XMLInputFactory
  .newInstance()
  .createXMLStreamReader(
		Reader::class.java.getResourceAsStream("data_part.xml")
	)

Поиск тэга

private val reader = reader()
while (reader.hasNext())
	when (reader.next()){
		XMLStreamReader.START_ELEMENT ->
			if (reader.localName == "CodeLists")
				readLists()
		XMLStreamReader.END_ELEMENT ->
			if (reader.localName == "CodeLists")
				break
	}

Поиск вложенного тэга

private fun readLists() {
    while (reader.hasNext())
        when (reader.next()) {
            XMLStreamReader.START_ELEMENT ->
                if (reader.localName == "CodeList")
                    readList()
            XMLStreamReader.END_ELEMENT ->
                if (reader.localName == "CodeLists")
                    return
        }

Выборка XML элемента

private fun readList() {
    while (reader.hasNext())
        when (reader.next()) {
            XMLStreamReader.START_ELEMENT ->
                if (reader.localName == "Name")
                    result += reader.elementText + "\n"
            XMLStreamReader.END_ELEMENT ->
                if (reader.localName == "CodeList")
                    return
        }
}

Усложненный пример StAX

class Point(
    var year: Int = 0,
    var period: String = "",
    var value: Float = 0f
){
    override fun toString(): String =
        "$year $period: $value\n"
}
private val result = ArrayList<Point>()

Выборка XML элемента

while (reader.hasNext())
	if (reader.next() == XMLStreamReader.START_ELEMENT)
		if (reader.localName == "Series")
			checkSeriesKey()
private fun checkSeriesKey() {
    while (reader.hasNext())
        when (reader.next()) {
            XMLStreamReader.START_ELEMENT ->
                if (reader.localName == "SeriesKey")
                    checkValue()
            XMLStreamReader.END_ELEMENT ->
                if (reader.localName == "Series")
                    return } }

Проверка дополнительных условий

private fun checkValue() { var rightValues = 0
  while (reader.hasNext()) when (reader.next()) {
    XMLStreamReader.START_ELEMENT ->
      if (reader.localName == "Value") {
        if ((reader.getAttributeValue(0) == "s_OKATO") and
          (reader.getAttributeValue(1) == "643")
        ) rightValues++
        if ((reader.getAttributeValue(0) == "s_OKVED2") and
          (reader.getAttributeValue(1) == "62")
        ) rightValues++
        if(rightValues==2) {
          readSeries() return } }
      XMLStreamReader.END_ELEMENT ->
        if (reader.localName == "SeriesKey") return } }

Чтение данных

private fun readSeries() {
    val point = Point()
    while (reader.hasNext())
        when (reader.next()) {
            XMLStreamReader.START_ELEMENT ->
                when (reader.localName) {
                    "Attributes" -> readAttributes(point)
                    "Obs" -> readObs(point) }
            XMLStreamReader.END_ELEMENT ->
                if (reader.localName == "Series"){
                    if(point.period!="")
                        result.add(point)
                    return } } }