Scala的初学者来自Java背景。假设我的代码中有一堆XML:
val x = <file> <name> some-file.txt </name> </file>
有什么办法可以将XML元素提取到命名常量中吗?我已尝试过以下操作,但它并不像第一行那样工作,它仍然期待关闭</file>
标记:
val FileStart = <file>
val FileEnd = </file>
我问,因为我想避免在我的代码中浮动的魔术值。我想到使用<name>
标签100次然后让它的价值在未来十个月内改变(这将导致可怕的标签搜寻)。我宁愿把它定义在一个常数的某个地方。
更好的是,是否有Scala方法可以有效地解决这个问题?也许我一直坚持Java思维。
答案 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>