Сопоставление NodeSeq не удается, но эквивалентное сопоставление Elem успешно - почему? как исправить? - PullRequest
3 голосов
/ 13 августа 2010

ОК, это ставит в тупик и меня (новичка в Scala), и моего коллегу (более продвинутого в Scala). Scala 2.8.0. Вот демонстрация проблемы:

// I've got a var with some XML in it
scala> qq2
res9: scala.xml.Elem = <a><a1>A1</a1><bs><b>B1</b><c>C1</c><d>D1</d></bs></a>

// I can extract sub-elements
scala> (qq2 \ "bs")
res10: scala.xml.NodeSeq = NodeSeq(<bs><b>B1</b><c>C1</c><d>D1</d></bs>)

// but if I try to match against this NodeSeq, it fails to match
scala> (qq2 \ "bs") match {case <bs>{x @ _*}</bs> => 
            for (xx <- x) println("matched " + xx) }      
scala.MatchError: <bs><b>B1</b><c>C1</c><d>D1</d></bs>
        at .<init>(<console>:7)
        at ...

// but if I just type in the XML directly, it works as expected
scala> <bs><b>B1</b><c>C1</c><d>D1</d></bs> match {
          case <bs>{x @ _*}</bs> => for (xx <- x) println("matched " + xx) }
matched <b>B1</b>
matched <c>C1</c>
matched <d>D1</d>

// presumably because it's of type Elem, not NodeSeq
scala> <bs><b>B1</b><c>C1</c><d>D1</d></bs>
res13: scala.xml.Elem = <bs><b>B1</b><c>C1</c><d>D1</d></bs>

Итак, два вопроса. Один: WTF? Почему это так? Второе: я не могу найти способ конвертировать NodeSeq в Elem, чтобы это совпадение работало. Какой правильный способ сделать это?

Ответы [ 2 ]

6 голосов
/ 13 августа 2010

A NodeSeq - это набор Node с, а не один узел:

scala> (<a><b>1</b><b>2</b></a>) \ "b"
res0: scala.xml.NodeSeq = NodeSeq(<b>1</b>, <b>2</b>)

Таким образом, вы должны сопоставить узлы:

scala> ((<a><b>1</b><b>2</b></a>) \ "b").map(_ match {
     |   case <b>{x}</b> => true
     |   case _ => false
     | })
res24: scala.collection.immutable.Seq[Boolean] = List(true, true)

(Узлы имеют тенденциюбыть Elems, так что это работает хорошо. Я не знаю причины разделения; я думаю, что некоторые узлы могут иметь меньше связанных с ними, чем Elem.)

4 голосов
/ 14 августа 2010

Метод \ возвращает последовательность правильных ответов, а не один элемент.Здесь:

scala> val qq2 = <a><a1>A1</a1><bs><b>B1</b><c>C1</c><d>D1</d></bs></a>
qq2: scala.xml.Elem = <a><a1>A1</a1><bs><b>B1</b><c>C1</c><d>D1</d></bs></a>

scala> (qq2 \ "bs") match {case Seq(<bs>{x @ _*}</bs>) => //<-I added a Seq()
     |     for (xx <- x) println("matched " + xx) }
matched <b>B1</b>
matched <c>C1</c>
matched <d>D1</d>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...