s.Doe
s.Doe

Reputation: 25

Get Xpath from command line in scala

import scala.io.Source
import scala.xml.{Node, NodeSeq, XML}

object scalaTest extends App {


var test= <name>person
<fname>doe
<first>john</first>
</fname>
</name>


var s=scala.io.StdIn.readLine
var result=s.asInstanceOf[NodeSeq]

println(result)


}

When i provide xpath test\"fname"\"first" on command line, it throws,

test\"fname"\"first"
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to scala.xml.NodeSeq
    at scalaTest$.delayedEndpoint$scalaTest$1(scalaTest.scala:15)
    at scalaTest$delayedInit$body.apply(scalaTest.scala:4)
    at scala.Function0.apply$mcV$sp(Function0.scala:34)
    at scala.Function0.apply$mcV$sp$(Function0.scala:34)
    at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
    at scala.App.$anonfun$main$1$adapted(App.scala:76)
    at scala.collection.immutable.List.foreach(List.scala:389)
    at scala.App.main(App.scala:76)
    at scala.App.main$(App.scala:74)
    at scalaTest$.main(scalaTest.scala:4)
    at scalaTest.main(scalaTest.scala)

How to provide xpath as test\"fname"\"first" in command line and get result as,

<first>john</first>

Upvotes: 0

Views: 77

Answers (1)

Andrey Tyukin
Andrey Tyukin

Reputation: 44957

You cannot just cast a String into a NodeSeq. You could attempt to parse it with XML.loadString(...). But this is also not what you want, because your string does not contain xml, it contains some xpath-like selection. I don't know whether Scala's built-in XML actually supports Xpath. I only know that it has a few funny methods on NodeSeqs like \ and \\ that look somewhat like Xpath. What you could do is:

  • get input string from stdin
  • split your input string at the '\'-character
  • foldLeft the test-xml node using the \-method

Something like this works:

import scala.xml.NodeSeq
val test = <name>person<fname>doe<first>john</first></fname></name>
val xpath = """fname\first""" // or read from StdIn
val selectedElement = xpath.split("\\\\").foldLeft[NodeSeq](test){
  case (elem, tagName) => elem \ tagName 
}

// gives result:
// res20: scala.xml.NodeSeq = NodeSeq(<first>john</first>)

Or shorter:

val selectedElement = xpath.split("\\\\").foldLeft[NodeSeq](test)(_ \ _)

Another note: you of course cannot use the String "test" in your StdIn input. How is the compiler supposed to know that it has anything to do with the local test-variable?

Upvotes: 1

Related Questions