与多行XML案例匹配的模式

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?

我当然试图通过谷歌找到答案.有趣的是,所有的例子都是单行或工作递归.

Rex*_*err 3

这比我最初想象的要丑陋得多。我确实有一个部分解决方案,但我不确定它是否值得付出努力。默认模式匹配将空格视为标记,并且我还没有找到任何干净的方法来绕过它。所以我做了相反的事情:用空格装饰输入字符串。这个例子只有一层缩进;您可以想象递归添加空格以匹配您最喜欢的缩进样式。

这是示例(需要编译并运行;至少 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)

相当不优雅,但它确实(勉强)实现了你想要的。