This chapter describes Scala's support for XML, including the main contents of this article at the level of headings.
A description of the concept and XML format of semi-structured data is skipped, directly into Scala's XML-related syntax and usage. First, XML syntax
The Scala command line can be entered directly at the beginning of a tag, and the compiler automatically enters the XML input pattern until it encounters a closing flag that matches the tag. As shown below:
scala> <a>
| This is some XML.
| Here's a tag: <atag/>
| </a>
Res25:scala.xml.Elem =
<a> This is
some XML.
Here is a tag: <atag/>
</a>
The above code gets an object of type Scala.xml.Elem. In Scala, other XML-related classes also include:
Node XML parent of all node classes
Text a node that contains only XML values. For example, the stuff part of <a>stuff</a>.
NODESEQ node sequence
In addition to entering the complete XML tags and values directly in the image above, you can dynamically compute the value part with {} in the value section. As shown in the following figure,
scala> <a> {"Hello" + ", World"} </a>
Res26:scala.xml.Elem = <a> Hello, world </a>
In the code above {} is a string concatenation expression, in {} can contain any form of Scala expression, such as if ... else ... And so on, you can also access variables defined in {}. Second, serialization
Serialization here refers to the conversion of an object into an XML form. Corresponds to the following deserialization.
The code shown below defines a cctherm abstract class.
Abstract class Cctherm {
val description:string
val yearmade:int
val dateobtained:string
val Bookprice:int//In US cents
Val purchaseprice:int//in US cents
Val condition:int//1
override Def toString = Description
def toXML =
<cctherm>
<description>{description}</description >
<yearMade>{yearMade}</yearMade>
<dateobtained>{dateobtained}</dateobtained >
<bookPrice>{bookPrice}</bookPrice>
<purchaseprice>{purchaseprice}</ purchaseprice>
<condition>{condition}</condition>
</cctherm>
}
The ToXml method in the above code can be converted to a Scala.xml.Elem type variable based on the properties of the Cctherm class.
The following code constructs an object of type Cctherm and invokes the ToXml method to convert the class to XML.
Val therm = new Cctherm {
val description = "Hot Dog #5"
val yearmade = 1952
val dateobtained = "March 14, 200 6 "
val bookprice = 2199
val purchaseprice =
val condition = 9
}
println (therm)
println ( Therm.toxml)
The results are as follows:
Hot dog #5
<cctherm>
<description>hot dog #5 </description>
<yearmade>1952 </yearMade>
<dateobtained>march, 2006</dateobtained>
<bookprice>2199</ bookprice>
<purchasePrice>500</purchasePrice>
<condition>9</condition>
</cctherm>
Finally, if you want to enter {or} in the content of the XML, you need to enter two at a time, as follows:
Scala> <a> {{{brace yourself!}}} </a>
Res27:scala.xml.Elem = <a> {brace yourself!}} </a >
third, XML data access
Of the multiple methods provided in the XML class, there are three methods that can be used to parse XML and get some of the information directly. 1, text method, get the value part of XML node
scala> <a>sounds <tag/> good</a>.text
res28:string = Sounds Good
2, \ Methods and \ Methods to get the child elements in the XML
(1) \ Method
Scala> <a><b><c>hello</c></b></a> \ "B"
Res4:scala.xml.NodeSeq = NodeSeq (<b><c>hello</c></b>)
Scala> <a><b><c>hello</c></b></a> \ "C"
Res5:scala.xml.NodeSeq = NodeSeq ()
scala> <a><b><c>hello</c></b></a> \ "B" \ "C"
res6: Scala.xml.NodeSeq = NodeSeq (<c>hello</c>)
scala> <a><b><c>hello</c> </b></a>.text
res7:string = Hello
As you can see from the figure above, the \ method returns an object of type NodeSeq, even if the specified child element has only one.
As you can see in the figure above, the text method can also get the value part directly in the nested XML.
(2) \ \ Method
The above \ method can only get the next layer of child elements, for example, direct access to the child element "C", the resulting empty nodeseq. If you want to access the "C" element directly and get the corresponding child element, then you need to use the \ method.
Scala> <a><b><c>hello</c></b></a> \ "C"
Res8:scala.xml.NodeSeq = NodeSeq ()
scala> <a><b><c>hello</c></b></a> \ "C"
Res9:scala.xml.NodeSeq = NodeSeq (<c>hello</c>)
scala> <a><b><c>hello</c></b></a> \ "A"
Res10:scala.xml.NodeSeq = NodeSeq ()
scala> <a><b><c>hello</c></b> </a> \ "A"
Res11:scala.xml.NodeSeq = NodeSeq (<a><b><c>hello</c></b></a >)
3, @ method, get the property value of the label
In the XML tab, you can specify some label properties. Labels with no attributes, such as <A/>, with attributes such as <a name= "x" age= "/>". Use the @ method to get the value of the ' name ', ' Age ' section.
The @ symbol needs to be used in conjunction with the ' or \ \ method.
Scala> val joe = <employee
| name= "Joe"
| rank= "code Monkey"
| serial= "123"/>
Joe: Scala.xml.Elem = <employee name= "Joe" rank= "code Monkey" serial= "123"/> scala>
Joe \ "@name"
res12: Scala.xml.NodeSeq = Joe
scala> joe \ "@serial"
res13:scala.xml.NodeSeq = 123
scala> joe \ "@x"
Res 14:scala.xml.nodeseq = NodeSeq ()
The method returns a variable of type NodeSeq. When you access a property that does not exist, you get an empty nodeseq. Iv. deserialization
Deserialization, in contrast to the serialization process described earlier, is a process used to convert an XML element into a generic object. Combining the three methods mentioned above, you can easily get the value of the specified element to convert the XML into a normal object.
Continue to add the FromXml method to the previous Cctherm class, as follows:
def fromxml (node:scala.xml.Node): Cctherm =
new Cctherm {
val description = (node \ "description"). Text
Val y Earmade = (node \ "Yearmade"). Text.toint
val dateobtained = (node \ "dateobtained"). Text
val bookprice = (node \ " Bookprice "). Text.toint
val purchaseprice = (node \ purchaseprice). text.toint
val condition = (node \" Condition "). Text.toint
}
v. Loading and saving
As you can see from the previous command-line pattern, the XML type's own ToString method can convert the contents of it to string.
However, it is best to use some of the methods provided by XML to manually convert the XML content into a string format for output. Because this output will contain some attributes, such as character encoding. 1, Scala.xml.XML.save method to save the XML content to the specified file
Use the following scala.xml.XML.save ("Therm1.xml", node). After execution, open Therm1.xml ', which reads as follows:
<?xml version= ' 1.0 ' encoding= ' UTF-8 '?>
<cctherm>
<description>hot dog #5 </description >
<yearMade>1952</yearMade>
<dateobtained>march, 2006</dateobtained>
<bookPrice>2199</bookPrice>
<purchasePrice>500</purchasePrice>
<condition >9</condition>
</cctherm>
2, XML. Xml.loadfile method to load the XML file directly into the Scala.xml.Elem object
Val Loadnode = XML as shown below. Xml.loadfile ("Therm1.xml"), the results of the operation are as follows:
<cctherm>
<description>hot Dog #5 </description>
<yearMade>1952</yearMade>
<dateobtained>march, 2006</dateobtained>
<bookPrice>2199</bookPrice>
<purchasePrice>500</purchasePrice>
<condition>9</condition>
</cctherm>
pattern matching in XML
So far, you've learned how to survive an XML type object and how to get the value of a specified element out of XML. But the methods described above are useful only if you know exactly what the XML file is, and you know what you're taking out of it. 1, pattern matching simple application
Pattern matching in XML is similar to XML expressions, except that the content in the XML expression {} is Scala code, but the content in the pattern match {} is a matching pattern.
Examples are as follows:
def proc (node:scala.xml.Node): String =
node Match {case
<a>{contents}</a> => "It's an A:" + cont Ents case
<b>{contents}</b> => "It's a B:" + contents Case
_ => "It s something else."
}
The results of the operation are as follows:
scala> proc (<a>apple</a>)
res15:string = It ' s an a:apple
scala> proc (<b>banana</b >)
res16:string = It ' s a b:banana
scala> proc (<c>cherry</c>)
res17:string = It ' s Somet Hing else.
However, the pattern matching above can only handle one layer of XML objects and cannot be resolved for nested XML as follows:
scala> proc (<a>a <em>red</em> apple</a>)
res18:string = It ' s something else.
scala> proc (<a/>)
res19:string = It ' s something else.
2, Pattern matching advanced application
We usually want the XML schema matching functionality to be more than simple, and it's best to match the nested XML elements. The XML node sequence is taken out of the nested XML. In pattern matching should be written in the form of _*.
The improved Proc method looks like this:
def proc (node:scala.xml.Node): String =
node Match {case
<a>{contents @ _*}</a> => "It's" an A: "+ Contents Case
<b>{contents @ _*}</b> => "It's a B:" + contents Case
_ => "It ' s something else."
}
There is a @ symbol in the code before _*, this is the variable binding mentioned in Scala pattern matching, by the @ symbol, you can bind the matching content to the contents variable, you can use the variable directly in the subsequent code.
The results of the operation are as follows
scala> proc (<a>a <em>red</em> apple</a>)
res20:string = It ' s an A:arraybuffer (A, <em >red</em>, Apple)
scala> proc (<a/>)
res21:string = It ' s an A:wrappedarray ()
Pattern matching is a better way to parse XML, look at the following example:
Val Catalog =
<catalog>
<cctherm>
<description>hot dog #5 </description>
<yearMade>1952</yearMade>
<dateobtained>march, 2006</dateobtained>
< bookprice>2199</bookprice>
<purchasePrice>500</purchasePrice>
<condition>9 </condition>
</cctherm>
<cctherm>
<description>sprite boy</description >
<yearMade>1964</yearMade>
<dateobtained>april, 2003</dateobtained>
<bookPrice>1695</bookPrice>
<purchasePrice>595</purchasePrice>
< condition>5</condition>
</cctherm>
</catalog>
See from your code that there are two <cctherm> child elements under the <catalog> label. But the results are printed as follows. This is because after the label <catalog>, the content contained is its child element, we can see at the beginning and end of the most of the label there is a newline, and there are two <cctherm> between the existence of line breaks.
Scala> Catalog Match {
| Case <catalog>{therms @ _*}</catalog> =>
| For (therm <-therms)
| println ("Processing:" +
| (therm \ "description"). Text)
|}
Processing:
processing:hot dog #5
processing:
processing:sprite Boy
You can see from the result that there is an empty element before and after each <catalog> label. You can skip these empty elements by using the following code to process the XML.
Scala> Catalog Match {
| Case <catalog>{therms @ _*}</catalog> =>
| for (therm @ <cctherm>{_*}</cctherm> <-therms)
| println ("Processing:" +
| (therm \ "description"). Text)
|}
Processing:hot dog #5
processing:sprite Boy