I am parsing a series of XML responses from a external data store. During which I must test for the existence of a child node and - if it exists - test its value. To achieve that I have the following code:
...
val properties = for {
val row <- root \\ "ResultDescription"
val cond:Boolean = checkDetectionNode(row) match {
case Some(nodeseq) => {
val txt = nodeseq.text.toLowerCase
if (txt contains "non-detect")
false
else
true
}
case None => true
}
if (cond)
val name = (row \ "CharacteristicName").text
if (charNameList.exists(s => s == name) == false)
} yield {
getObservedProperty(name) match {
case Some(property) => {
charNameList = name :: charNameList
property
}
}
}
...
checkDetectionNode is defined as such:
private def checkDetectionNode(row: scala.xml.NodeSeq) : Option[scala.xml.NodeSeq] = {
if ((row \ "ResultDetectionConditionText") != null)
Some[scala.xml.NodeSeq]((row \ "ResultDetectionConditionText"))
else
None
}
The above code results in an unspecified error of "illegal start of simple expression" on the val name...
line. To be honest I am not a Scala programmer or even a functional programmer (always was more partial to OO/imperative). I've only been using Scala for a few days and been basing most of what I know from Java and lambda operators. Unfortunately, I don't really have the time to sit down and really learn Scala like I wish I could. Deadlines, make fools of us all.
I am hoping that someone could take a look and let me know if there is something I am doing wrong (as I am sure there is). I tried to limit the code shown to, what I hope, is relevant to the question. However, please let me know if any additional code is needed.
Thanks
First of all, note that (row \ "ResultDetectionConditionText")
won't be null
if no children with that name exist—it will just be an empty NodeSeq
(idiomatic Scala code tends to avoid returning null
, as you've probably noticed). So your current code will always return a Some
, which probably isn't what you want. Changing your != null
to .nonEmpty
will fix that problem.
Next, here's a more concise way of writing your conditional logic:
val cond = (row \ "ResultDetectionConditionText").exists(
_.text.toLowerCase contains "non-detect"
)
This says: get a NodeSeq
that contains all the children named "Result..."
, if they exist, and then check that NodeSeq
for a node that contains the text "non-detect"
. The logic's not exactly the same as yours, since we check the text of the nodes individually, but it actually fits what I'd guess is your intent even better—presumably you don't want something like this to pass the test:
val row = <row>
<ResultDetectionConditionText>non-d</ResultDetectionConditionText>
<ResultDetectionConditionText>etect</ResultDetectionConditionText>
</row>
But it will in your current version.
But none of this solves your "illegal start of simple expression"
issue—it just fixes the logic and cuts sixteen lines of code down to three. The problem here is that you need to decide what your name
should be if the test you've just done fails. The most obvious approach is to use an Option
:
val name = if (cond) Some((row \ "CharacteristicName").text) else None
But depending on how you're using name
, some other approach may be more appropriate.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With