Scala is yet another modern programming language which has received a lot of attention in the last few years. It compiles down to Java bytecode, therefore can take full advantage of existing Java libraries.
I'd like to take a few moments to share a couple of examples of one area that I think Scala shows great strength, processing of XML data. For my examples, I will be using XML data that has been aquired through using the WebSphere Portal tool,
xmlaccess. This tool accesses a portal instance's configuration data and returns an XML file that can in turn be used to modify the portal's configuration.
So, assuming we have an XML file that has been created via xmlaccess, we can then use Scala to process it. To load the file, we define a Scala object, import some library packages, and then call :
object ScalaXML extends Application {
import scala.xml._
import scala.collection.mutable.HashMap
import scala.collection.jcl.ArrayList
import java.util.Set
import java.util.HashSet
import java.util.Map
import java.util.TreeMap
//
// Load the XML file
//
val xml = XML.loadFile("test.xml")
In Scala, the '_' symbol serves the same purpose as the '*' in Java in an import statement. The XML.loadFile takes a file path, and creates a
val variable, which is immutable. The value in the variable 'xml' is now the parsed XML data. This statement displays the simplicity of coding that is also makes Scala very powerful. Java would require several lines of code to do the same thing.
Next, we do a simple XML pattern match to find the version of the XML data that is in the xmlaccess file.
//
// Search for an XML element with an attribute named
// 'version', and print out the value of that attribute
//
println("Version " + ( xml \\ "@version").text)
The
text method is a method on the
Node class, and is used to access the 'version' attribute's value. The method
println is a method on the Scala class
scala.Console, which is implicitly imported.
Here is an example of creating a Scala
Map of the elements from the file:
//
// Create a Scala Map by pattern matching 'Skin' elements
// The map's value object is the map of attributes
//
var oidMap = new HashMap[String, MetaData]
for (val entry <- xml \\ "skin") {
val objectid = (entry \\ "@objectid").text
val attributes = entry.attributes
oidMap += (objectid -> attributes)
}
The Scala Map functions the same as a Java Map, but uses some different syntax for adding objects. The '+=' symbol is actually a method defined on the class HashMap. In this example, the variable 'objectid' is the map's key, and 'attributes' is the map's value for each entry. We have a for loop here, in which the values of an XML pattern match are assigned to the val variable 'entry'.
To illustrate usage of a Java class in Scala, here is the same for loop, but now we are creating a Java TreeMap:
//
// Create a Java Map of the same elements
// The Set's value object is again the attributes
//
var oidJavaMap = new TreeMap[String,MetaData];
for (val entry <- xml \\ "skin") {
val objectid = (entry \\ "@objectid").text
val attributes = entry.attributes
oidJavaMap.put(objectid, attributes)
}
Now, let's process the Scala Map:
//
// Now iterate through the Scala Map to create
// a new List of Node which contains new Element
// objects replicating the original XML for the Skin
//
println("Iterating through Scala Map");
var nodes = new ArrayList[Elem]()
oidMap.foreach{ (nvPair) =>
val objectid = nvPair._1
val attributes = nvPair._2
var elem =
var newElem = elem.%(attributes)
nodes += newElem
}
This loop will create a new Scala
ArrayList. The
foreach construct allows you to iterate through the Scala Map, executing the body of code enclosed in the braces (a
closure) with the argument 'nvPair'. Closures are common in functional languages like Scala, where functions can be passed around as arguments. The elements of our new list are of type
Elem, even though we do not explicitly declare a variable of this type. Scala is able to infer the type of the variable from the text on the right side of the '=', which is a well-formed XML tag. The '%' operator is a method on Elem, an returns a new Element that contain the updated attributes in the variable 'attributes'. Because we are operating on a Map, the variable 'nvPair' is a key-value pair, which can be access with the _1 and _2 syntax for key and value, respectively.
We can output our new list as XML by doing the following:
//
// Create a new XML snippet with the Node objects from above
//
def xmlString =
xsi:noNamespaceSchemaLocation="PortalConfig_6.0.1_1.xsd">
{nodes}
//
// Output a prettied-up version of the new XML
//
println( new PrettyPrinter(80 /*width*/,4 /*indent*/).format(xmlString) )
This code shows us again how you create an XML object by simply in-lining the XML data. You can also embed the values of variables in this XML, as we do with the variable 'nodes'. Scala provides a built-in "pretty print" class,
PrettyPrinter, which is used to make the output more readable.
The last bit of example code shows how you can use what looks like plain old Java to iterate through our previously created Java Map.
//
// Iterate through the Java Map and print out some attributes
//
cnt = 0;
println("Iterating through Java Map");
var iterMap = oidJavaMap.keySet().iterator();
while (iterMap.hasNext()) {
var key = iterMap.next();
var attributes = oidJavaMap.get(key)
var objectid = attributes.get("objectid")
println("Objectid " + cnt + " is " + objectid.get)
var resourceroot = attributes.get("resourceroot")
println("Resourceroot " + cnt + " is " + resourceroot.get)
var uniquename = attributes.get("uniquename")
println("Unique name " + cnt + " is " + uniquename.get)
cnt += 1
}
This is pretty straight-forward code, and look almost identical to Java code. You might notice how we access indvidual attribute values with two different
get methods. This first is a method on the class MetaData, which is the abstract base class for the element's attributes. This returns an
Option object, which also has a get method. This second invocation returns the value of the attribute.
In WebSphere Portal xmlaccess, Scala
Comment (0)
Read More...