Is There a More Functional Way?

I am new at SCALA and finally found something that I can use it for at work.

Okay I am parsing the following XML sample from a RDL file

<DataSources>
<DataSource Name="DataSource1">
  <rd:SecurityType>Integrated</rd:SecurityType>
  <ConnectionProperties>.
    <DataProvider>SQL</DataProvider>
    <ConnectString>Server=localhost\SQLEXPRESS;Database=RDL;Trusted_Connection=True;</ConnectString>
    <IntegratedSecurity>true</IntegratedSecurity>
  </ConnectionProperties>
  <rd:DataSourceID>51d93eb3-b649-407b-949f-d577f64010d4</rd:DataSourceID>
</DataSource>
<DataSource Name="DataSource2">
  <rd:SecurityType>Integrated</rd:SecurityType>
  <ConnectionProperties>
    <DataProvider>Oracle</DataProvider>
    <ConnectString>Server=localhost\SQLEXPRESS;Database=NPL;Trusted_Connection=True;</ConnectString>
    <IntegratedSecurity>true</IntegratedSecurity>
  </ConnectionProperties>
  <rd:DataSourceID>51d93eb3-b649-407b-949f-d577f64010d4</rd:DataSourceID>
</DataSource>
  </DataSources>

I want to take the Datasouce Name, DataProvider, ConnectString and put the values into a db table or create an HTML file.

This is my code so far, but I know it has to be a more functional way to do this.

import scala.xml.*

val xfile = xml.XML.load("e:\\RDLFiles\\Test.rdl")
def createMap(list: List[String]): Map[String, String] = {
     val slist =  list.map(text => text.split("=")).map(a => (a(0) -> a(1))).toMap
     println(slist)
     slist
}
def createDataSource(list: List[String]): Unit = {
    val dsData = createMap(list)
    println(dsData("dataSourceName"))
    println(dsData("dataProvider"))
    println(dsData("connectString"))
}

def processDataSources  = {
( xfile \ "DataSources").flatMap { dss =>
    (dss \ "DataSource").flatMap { ds =>
        (ds \ "ConnectionProperties").flatMap { c =>
            (c \ "DataProvider").map { p =>
                (c \ "ConnectString").map { cs =>
                    Seq("dataSourceName="+ds \@ "Name",
                        "dataProvider="+p.text.toString,
                        "connectString="+ cs.text.toString.replace("=","->")
                    )
                }
            }
        }
    }
}.flatten.foreach(p=>createDataSource(p.toList))

}
processDataSources



Any suggestions would be appreciated
1 Like
  • use proper data types
  • flatMap rather than map with subsequent flatten
  • use for expression

Naive attempt:

case class DataSource(
  dataSourceName: String,
  dataProvider: String,
  connectString: String
)

def extractDataSources(dsXml: Elem): Seq[DataSource] =
  for {
    ds <- dsXml \ "DataSources" \ "DataSource"
    c <- ds \ "ConnectionProperties"
    p <- c \ "DataProvider"
    cs <- c \ "ConnectString"
  } yield DataSource(ds \@ "Name", p.text, cs.text.replace("=", "->"))
4 Likes