Scala XML pattern matching, top level element

时间:2019-04-08 12:51:58

标签: xml scala scala-xml

Consider the following XML node:

 <Interval>
   <P v="1"/>
   <Q v="0.0"/>
  </Interval>

What is the correct way to pattern match the top level element in Scala? I would expect the following to work but it does not:

def visit(node:Node):String = {
    node match {
        case p @ <P/> => (p \ "@v") text
        case q @ <Q/> => (q \ "@v") text
        case <Interval> @ children:_* </Interval> => "parent"
    }
}

2 个答案:

答案 0 :(得分:2)

在Scala中创建XML文字时,分配给它的变量 是顶级元素。

val node: scala.xml.Elem =
  <Interval>
   <P v="1"/>
   <Q v="0.0"/>
  </Interval> 

要匹配顶级元素(例如IntervalInterval中具有子元素的任何元素,例如您的示例),可以使用大括号来匹配子元素。

node match {
  case <Interval>{ children @_* }</Interval> => children.collect {
    case p @ <P/> => p \@ "v"
    case q @ <Q/> => q \@ "v"
  }
}

结果是:

Seq("1", "0.0")

如果您不熟悉collect,则可以使用它提供部分函数(读为“模式匹配”),并忽略否则会由于匹配错误而失败的情况。

答案 1 :(得分:0)

scala中的此表达式:

<Interval>
 <P v="1"/>
 <Q v="0.0"/>
</Interval>

肯定会在scala中返回scala.xml.Node,但首先返回scala.xml.Elem。您可以像这样对它进行图案匹配:

import scala.xml.Elem

def visit(elem: Elem) = {
    elem match {
        case e@Elem(_, "Interval",_, _, _*) => "identified!"
    }
}

或者您也可以在child上进行模式匹配,因为您在类型Elem的对象n上进行模式匹配就像Elem(n.prefix, n.label, n.attributes, n.scope, n.child)以及此处的child元素(这是一个Seq)与模式的其余每个元素匹配:

def visit(elem: Elem) = {
    elem match {
        case Elem(_, "Interval",_, _, emptyElem, nodeIWant@(<P/>), _*) =>
        (nodeIWant \ "@v").text
    }
}

例如在此处返回1

希望有帮助。