2012-09-06 5 views
5

私は外部データストアから一連のXML応答を解析しています。その間、私は子ノードの存在をテストしなければならず、存在する場合はその値をテストしなければなりません。Scala XML:ノードの存在と値のテスト

... 
    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は、このような次のように定義されます:val name...ライン上で「単純な式の違法開始」の不明なエラーで

private def checkDetectionNode(row: scala.xml.NodeSeq) : Option[scala.xml.NodeSeq] = { 
    if ((row \ "ResultDetectionConditionText") != null) 
    Some[scala.xml.NodeSeq]((row \ "ResultDetectionConditionText")) 
    else 
    None 
} 

上記のコードの結果、私は次のコードを持っていることを達成するために。正直言って私はScalaのプログラマではなく、機能的なプログラマでもありません(常にOO /必須の部分的でした)。私は数日間Scalaを使用してきただけで、私がJavaとラムダ演算子から知っているものの大半を基にしています。残念ながら、座って本当にスカラを学ぶ時間はありません。締め切りは、私たちすべての愚か者を作る。

私は間違っていることがあるかどうかを誰かが見て、私に知らせることを望んでいます(私はそこにいると確信しています)。私は、表示されたコードを、私が望むところで、その質問に関連するものに限定しようとしました。ただし、追加のコードが必要な場合はお知らせください。

おかげ

+0

私は上記のことが声明の理解の一部であることを明確にすべきだと思います。 'if(cond)'は、yieldブロックの実行を決定するためのものです。私は、コードについて詳しく説明するために私の答えを編集しました。 – Cowan

答えて

1

xmlはここで注意散漫です。問題は、最後のif(cond)がガードの役目を果たさないことです。コンパイラは新しいif 'then'部分の開始と考えます。次の例では

:ご想像のとおり

val l = List(1,2,3,4,5) 

val r = for { 
    i <- l 
     if (i > 2) 
    x <- Some(i * 2) 
    } yield x 

あなたはリスト(6,8,10)を取得します。使用

val r = for { 
    val i <- l if (i > 2) 
    val x <- Some(i * 2) 
    } yield x 

あなたの廃止の警告を取得し、

val r = for { 
    val i <- l 
    if (i > 2) 
    val x <- Some(i * 2) 
    } yield x 

は、単にあなたの発電機の前でのvalを削除

error: illegal start of simple expression 
    val x <- Some(i * 2) 

を取得する必要があります(パターン1 '< - ' Expr [Guard])、通常のサービスを再開できます。私が見つけたforループにはvalがなくても少しうまく流れます。

+0

これは質問に直接関係する最良の答えです。残念ながら、これにより私は問題を再考し、重大な書き直しをしました。 – Cowan

0

if (cond)は、式が続くべきです。 Scalaでは、ifはJavaの三項演算子によく似ています。これは式であり、文ではありません。変数宣言は(Javaの場合のように)式ではないため、ifの部分にvalを含めることはできません。

正直言って、私はあなたがそこで達成したいと思うことができないので、理にかなった構文的に正しい代替案を提案することはできません。しかし、あなたがcondに依存してより多くのロジックを持っている場合、あなたはブロックでそれを置くことができます:すべての

if (cond) { 
    val name = ... 
    // do more here 
} 
+0

簡潔な応答をありがとう。私はif文が条件付き演算子として機能することを忘れていました。しかし、このケースでは、if文を三項演算子からyield文の条件付きの要件に変更すると考えています。上記の私の質問を改訂し、より多くのコードを追加しました。 – Cowan

3

まず、その名前の子が存在しない、それを場合(row \ "ResultDetectionConditionText")nullではありませんだけになることに注意してください空のNodeSeq(慣用的なScalaコードはおそらく気付いたようにnullを返す傾向があります)。したがって、現在のコードは常にSomeを返します。これはおそらくあなたが望むものではありません。 != null.nonEmptyに変更すると、その問題が解決されます。

次は、ここにあなたの条件ロジックを書くより簡潔な方法です:

val cond = (row \ "ResultDetectionConditionText").exists(
    _.text.toLowerCase contains "non-detect" 
) 

これは言う:彼らが存在する場合は、"Result..."という名前の子をすべて含むNodeSeqを取得し、そのノードのためにそのNodeSeqをチェックそのテキストには"non-detect"が含まれています。私たちはノードのテキストを個別にチェックするので、論理はあなたとまったく同じではありませんが、実際にはあなたの意図がさらに良くなっていると思われます。

val row = <row> 
    <ResultDetectionConditionText>non-d</ResultDetectionConditionText> 
    <ResultDetectionConditionText>etect</ResultDetectionConditionText> 
</row> 

しかし、現在のバージョンになります。

しかし、"illegal start of simple expression"の問題は解決されません。ロジックを修正して16​​行のコードを3つに減らすだけです。ここで問題となるのは、実行したテストが失敗した場合に、nameが何をすべきかを決定する必要があるということです。最も明白なアプローチはOptionを使用することです:

val name = if (cond) Some((row \ "CharacteristicName").text) else None 

しかし、あなたはnameを使用している方法に応じて、他のいくつかのアプローチがより適切かもしれません。

+0

これらの問題を指摘していただき、ありがとうございます。これらの変更をコードに適用します。私は、これが包括的であることを指摘するために私の質問を編集しました。これは、間違っている可能性があり、if文の三項の性質を変えると考えています。 – Cowan

関連する問題