解析xml导致匹配错误与新行

时间:2015-02-12 22:17:53

标签: scala xml-parsing

您试图使用模式匹配来解析xml 以下课程:

sealed trait Predicate
case class Single(name:String) extends Predicate
case class Or(ps: Seq[Predicate]) extends Predicate
case class And(ps: Seq[Predicate]) extends Predicate

这是我的解析器

object RuleParser {
  def parse(ns: NodeSeq):Predicate ={
    println(ns.toString())
    ns match  {
      case <AND>{ xs @ _* }</AND> => And(xs map parse)
      case <OR>{ xs @ _* }</OR> => And(xs map parse)
      case <name>{ s @ _* }</name> =>Single(s.text)
    }
  }
 }

然而,当我发送这个

 val elm1 =
      <AND>
        <name> John </name>
      </AND>

    RuleParser.parse(elm1)

我收到模式匹配错误。 但尝试这个时:

val elm2 = <AND><name> John </name></AND>
RuleParser.parse(elm2)

没关系。

为什么? 问题是我正在读取一个文件,它的结构有多行(如elm1)

我也试过像这样加载文件

  val src = scala.io.Source.fromFile("/home/buzz/foo.xml")
  val fxml = ConstructingParser.fromSource(src, false).document.docElem
RuleParser.parse(fxml)

但遇到了同样的问题

任何想法如何解决这个问题?

BTW我正在使用2.11.4

2 个答案:

答案 0 :(得分:1)

在您的第一个示例中,您似乎没有处理AND元素之前和之后name元素内发生的文本节点。

答案 1 :(得分:1)

在存在空白文本节点的情况下,圣经有a section describing pattern matching个文字。

插图:

scala> <X>
     |      <Y/>
     |   </X>
res0: scala.xml.Elem =
<X>
     <Y/>
  </X>

scala> .child
res1: Seq[scala.xml.Node] =
ArrayBuffer(
     , <Y/>,
  )

scala> val xml.Text(s) = res1(0) 
s: String =
"
     "

库的MarkupParser可以选择关闭您在示例中使用的“保留空格”。这应该可行。

例如:

import scala.xml._, parsing._

sealed trait Predicate
case class Single(f: String => Boolean) extends Predicate
case class Or(ps: Seq[Predicate]) extends Predicate
case class And(ps: Seq[Predicate]) extends Predicate

object RuleParser {
  def parse(ns: NodeSeq):Predicate ={
    println(s"Parse: ${ns.toString}")
    ns match  {
      case <AND>{ xs @ _* }</AND> => And(xs map parse)
      case <OR>{ xs @ _* }</OR> => And(xs map parse)
      case <name>{ s @ _* }</name> =>Single(_ == s.text)
    }
  }
}

object Test extends App {
  val src  = scala.io.Source.fromFile("foo.xml")
  val fxml = ConstructingParser.fromSource(src, preserveWS = false).document.docElem
  //val fxml = ConstructingParser.fromFile(new java.io.File("foo.xml"), preserveWS = false).document.docElem
  println(RuleParser.parse(fxml))
  val e1 =
         <AND>
           <name> John </name>
         </AND>
  println(RuleParser.parse(e1))
}

使用foo.xml:

<AND>
                    <name> John </name>
                    </AND>

产生

Parse: <AND><name>John</name></AND>
Parse: <name>John</name>
And(List(Single(<function1>)))
Parse: <AND>
           <name> John </name>
         </AND>
Parse: 

scala.MatchError: 
            (of class scala.xml.Text)
    at xmlp.RuleParser$.parse(xmlp.scala:14)