Joa*_*ert 6 xml scala pattern-matching
我一定是在做一些愚蠢的错误.我有一个返回XML的服务器,<a><b>123</b></a>现在我想与该XML匹配.所以我写了类似的东西
xml match {
case <a><b>{_}</b></a> => true
}
Run Code Online (Sandbox Code Playgroud)
只要我不必处理多行XML文字,这就可以工作.所以重要的是服务器将整个XML作为单行发送给我.XML大到足以爆炸一行代码,但我无法弄清楚如何让它工作.
服务器发送<a><b>123</b><c>123</c><d>123</d><e>123</e><f>123</f></a>,我想这样做:
xml match {
case <a>
<b>{_}</b>
<c>{valueOfC}</c>
<d>{_}</d>
<e>{_}</e>
<f>{_}</f>
</a> => valueOfC
}
Run Code Online (Sandbox Code Playgroud)
但我总是得到一个MatchError.如果我在一行中写下所有内容就行了.所以问题是:如何在编写人类可读代码时匹配XML?
我当然试图通过谷歌找到答案.有趣的是,所有的例子都是单行或工作递归.
这比我最初想象的要丑陋得多。我确实有一个部分解决方案,但我不确定它是否值得付出努力。默认模式匹配将空格视为标记,并且我还没有找到任何干净的方法来绕过它。所以我做了相反的事情:用空格装饰输入字符串。这个例子只有一层缩进;您可以想象递归添加空格以匹配您最喜欢的缩进样式。
这是示例(需要编译并运行;至少 2.7 REPL 似乎不喜欢 case 语句中的多行 XML)。
object Test {
import scala.xml._
def whiten(xml: Node,w:String): Node = {
val bits = Node.unapplySeq(xml)
val white = new Text(w)
val ab = new scala.collection.mutable.ArrayBuffer[Node]()
ab += white;
bits.get._3.foreach {b => ab += b ; ab += white }
new Elem(
xml.prefix,
xml.label,
xml.attributes,
xml.scope,
ab: _*
);
}
val xml = <a><b>123</b><c>Works</c></a>
def main(args:Array[String]) {
whiten(xml,"""
""" // You must match the multiline whitespace to your case indentation!
) match {
case <a>
<b>123</b>
<c>{x}</c>
</a> => println(x)
case _ => println("Fails")
}
}
}
Run Code Online (Sandbox Code Playgroud)
相当不优雅,但它确实(勉强)实现了你想要的。