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!