How to generate XML with Kotlin Extension functions and Lambdas in Android app

 

Working with JSON is like a piece of cake to any mobile developer. Unfortunately, sometimes we may need to work with XML as well to support age old webservice APIs. There are several ways to generate XML in android, but none looks fancy to me, all seems verbose, error prone, and overkill. While searching for a way to fix this, I reached here. The author had used Kotlin Extension functions and Lambdas very well to avoid verbose in XML generation. Being a Kotlin fan and after trying a while, I made few extension functions to generate XML that makes life hell of a lot easier.

Let us consider the required XML as below,

<?xml version="1.0" encoding="UTF-8"?>
<Movies>
   <row no="1">
      <FL val="TicketId">6000000066015</FL>
      <FL val="MovieName">Dunkirk</FL>
      <FL val="TimeLog">
         <row no="1">
            <FL val="date">23/01/2018</FL>
            <FL val="startTime">08:00</FL>
         </row>
      </FL>
   </row>
</Movies>

One of the ugliest, toughest, verbose, error prone way…

val xmlSerializer = Xml.newSerializer()
val writer = StringWriter()
xmlSerializer.setOutput(writer)
xmlSerializer.startDocument("UTF-8", false)
xmlSerializer.startTag("", "Movies")
xmlSerializer.startTag("", "row")
xmlSerializer.attribute("", "no", "1")
xmlSerializer.startTag("", "FL")
xmlSerializer.attribute("", "val", "TicketId")
xmlSerializer.text("6000000066015")
xmlSerializer.endTag("", "FL")
xmlSerializer.startTag("", "FL")
xmlSerializer.attribute("", "val", "MovieName")
xmlSerializer.text("Dunkirk")
xmlSerializer.endTag("", "FL")
xmlSerializer.startTag("", "FL")
xmlSerializer.attribute("", "val", "TimeLog")
xmlSerializer.startTag("", "row")
xmlSerializer.attribute("", "no", "1")
xmlSerializer.startTag("", "FL")
xmlSerializer.attribute("", "val", "logDate")
xmlSerializer.text("23/01/2018")
xmlSerializer.endTag("", "FL")
xmlSerializer.startTag("", "FL")
xmlSerializer.attribute("", "val", "startTime")
xmlSerializer.text("08:00")
xmlSerializer.endTag("", "FL")
xmlSerializer.endTag("", "row")
xmlSerializer.endTag("", "FL")
xmlSerializer.endTag("", "row")
xmlSerializer.endTag("", "Movies")
xmlSerializer.endDocument()
println(writer.toString())

Easiest, Elegant, and human readable way…

val xmlSerializer = Xml.newSerializer()
val xmlString = xmlSerializer.document {
            element("Movies") {
                element("row") {
                    attribute("no", "1")
                    element("FL", "6000000066015") {
                        attribute("val", "TicketId")
                    }
                    element("FL", "Dunkirk") {
                        attribute("val", "MovieName")
                    }
                    element("FL") {
                        attribute("val", "TimeLog")
                        element("row") {
                            attribute("no", "1")
                            element("FL", "23/01/2018") {
                                attribute("val", "date")
                            }
                            element("FL", "08:00") {
                                attribute("val", "startTime")
                            }
                        }
                    }
                }
            }
        }
println(xmlString)

And the Extension functions are,

//  XML generation by code
fun XmlSerializer.document(docName: String = "UTF-8",
                           xmlStringWriter: StringWriter = StringWriter(),
                           init: XmlSerializer.() -> Unit): String {
    startDocument(docName, true)
    xmlStringWriter.buffer.setLength(0) //  refreshing string writer due to reuse
    setOutput(xmlStringWriter)
    init()
    endDocument()
    return xmlStringWriter.toString()
}

//  element
fun XmlSerializer.element(name: String, init: XmlSerializer.() -> Unit) {
    startTag("", name)
    init()
    endTag("", name)
}

//  element with attribute & content
fun XmlSerializer.element(name: String,
                          content: String,
                          init: XmlSerializer.() -> Unit) {
    startTag("", name)
    init()
    text(content)
    endTag("", name)
}

//  element with content
fun XmlSerializer.element(name: String, content: String) =
        element(name) {
            text(content)
        }

//  attribute
fun XmlSerializer.attribute(name: String, value: String) =
        attribute("", name, value)

That’s it! refer my gist for more.

Happy Coding!

Source: https://medium.com/audhil/how-to-generate-xml-with-kotlin-extension-functions-and-lambdas-in-android-app-976229f1e4d8

Share :

Leave a Reply

Your email address will not be published. Required fields are marked *


The reCAPTCHA verification period has expired. Please reload the page.