在Scala中将XML提取为常量的任何方法?

时间:2014-04-16 04:02:14

标签: xml scala

Scala的初学者来自Java背景。假设我的代码中有一堆XML:

val x = <file> <name> some-file.txt </name> </file>

有什么办法可以将XML元素提取到命名常量中吗?我已尝试过以下操作,但它并不像第一行那样工作,它仍然期待关闭</file>标记:

val FileStart = <file>
val FileEnd = </file>

我问,因为我想避免在我的代码中浮动的魔术值。我想到使用<name>标签100次然后让它的价值在未来十个月内改变(这将导致可怕的标签搜寻)。我宁愿把它定义在一个常数的某个地方。

更好的是,是否有Scala方法可以有效地解决这个问题?也许我一直坚持Java思维。

2 个答案:

答案 0 :(得分:4)

您的建议不是很好,如下所示:

val FileStart = <file>
val FileEnd = </file>

不创建并为变量分配有效的XML节点,这是编译期间需要和验证的。更令人意外的是,Scala编译器会将上述内容解释为单个节点FileStart的定义,作为<file>val FileEnd = </file> XML节点;)

由于您担心有多个name标记可能需要更改节点名称,因此我建议定义一组单独的可重用方法,即:

def nameNode(name : String) = <name>{name}</name>

def fileNode(name : String) = <file>{nameNode(name)}</file>

def createXml(files : List[String]) = <myLovelyFiles>
  {files.map(fileNode)}
</myLovelyFiles>

通过这种方式,您不仅可以避免重复标记名称100次,而且在构建XML时还需要测试一些复杂的功能,而且还有一个小的可测试单元。

希望这有帮助。

答案 1 :(得分:1)

提取:

scala> val x = <file> <name> some-file.txt </name> </file>
x: scala.xml.Elem = <file> <name> some-file.txt </name> </file>

scala> import xml.Elem
import xml.Elem

scala> x match { case Elem(prefix, label, attrs, ns, children @ _*) => println(label) }
file

scala> val File = "file"
File: String = file

scala> x match { case Elem(prefix, File, attrs, ns, children @ _*) => println(children) } 
ArrayBuffer( , <name> some-file.txt </name>,  )

scala> x match { case Elem(prefix, File, attrs, ns, children @ _*) => children \\ "name" }
res4: scala.xml.NodeSeq = NodeSeq(<name> some-file.txt </name>)

File不能以小写字母开头,否则它是变量。

嗯,如果您在不使用模式中的文字标记的情况下提取节点,那就是这样。

如果你想在不使用文字的情况下构建节点,你也可以这样做:

scala> val n = <name> some-file.txt </name>
n: scala.xml.Elem = <name> some-file.txt </name>

scala> val file = "file"
file: String = file

scala> import xml._
import xml._

scala> val f = Elem(null, file, Null, TopScope, minimizeEmpty = false, n)
f: scala.xml.Elem = <file><name> some-file.txt </name></file>

这是一个很好的语法:

https://github.com/lihaoyi/scalatags#hello-world

专注于制作HTML文字。

scala> val tag = "file"
tag: String = file

scala> val file: Node => Node = Elem(null, tag, Null, TopScope, true, _)
file: scala.xml.Node => scala.xml.Node = <function1>

scala> file { <name> some-file.txt </name> }
res0: scala.xml.Node = <file><name> some-file.txt </name></file>