2

I am trying to write a module that will convert XML to object/map. The xml can be anything so we cannot predefine a model class like we do for XStream/SAX Parser(I tried both). Is there any way to write a generic module that will convert any given XML to a Map or Object?

2 Answers 2

1

This question is interesting to me also. I tried to convert any xml object to Map[String, String].

<offer>
<model>superModel</model>
<vendor>superVendor</vendor>
<params>
<param1>p1</param1>
<param2>p2</param2>
</params>
</offer>

Result Map[String, String]:

Map(
"model" -> "superModel"
"vendor" -> "superVendor",
"params.param1" -> "p1",
"params.param2" -> "p2"
)
Sign up to request clarification or add additional context in comments.

Comments

0

This works:

val emptyMap = Map.empty[String,List[String]]

def xml2map(xml: String): Map[String,List[String]] = add2map(XML.loadString(xml), "", emptyMap)

private def add2map(node: Node, xPath: String, oldMap: Map[String,List[String]]): Map[String,List[String]] = {

  val elems = node.child.filter(_.isInstanceOf[Elem])
  val xCurr = xPath + "/" + node.label

  val currElems = elems.filter(_.child.count(_.isInstanceOf[Elem]) == 0)
  val nextElems = elems.diff(currElems)

  val currMap = currElems.foldLeft(oldMap)((map, elem) => map + {
    val key = xCurr + "/" + elem.label

    val oldValue = map.getOrElse(key, List.empty[String])
    val newValue = oldValue ::: List(elem.text)

    key -> newValue
  })

  nextElems.foldLeft(currMap)((map, elem) => map ++ add2map(elem, xCurr, emptyMap))
}

For the XML below

<Student>
<StudentID>123456</StudentID>
<AdmissDate>2018-09-03</AdmissDate>
<Timetable>
    <CurrentTerm>
        <StartDt>2018-09-03</StartDt>
        <EndDt>2018-12-31</EndDt>
        <Subject>Maths</Subject>
        <Subject>Physics</Subject>
        <Subject>History</Subject>
    </CurrentTerm>
</Timetable>

it returns a Map[String,List[String]] that looks like (after .toString()):

Map(
  /Student/Timetable/CurrentTerm/EndDt -> List(2018-12-31),
  /Student/Timetable/CurrentTerm/StartDt -> List(2018-09-03),
  /Student/Timetable/CurrentTerm/Subject -> List(Maths, Physics, History),
  /Student/AdmissDate -> List(2018-09-03),
  /Student/StudentID -> List(123456)
)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.