2012-09-06 10 views
5

Estoy analizando una serie de respuestas XML desde un almacén de datos externo. Durante el cual debo probar la existencia de un nodo hijo y, si existe, probar su valor. Para lograr que tengo el siguiente código:Scala XML: prueba de la existencia y el valor del nodo

... 
    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 se define como tal:

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

Los anteriores resultados de código en un error no especificado de "inicio ilegal de expresión simple" en la línea val name.... Para ser sincero, no soy un programador de Scala o incluso un programador funcional (siempre fue más parcial con OO/imperativo). Solo he estado usando Scala por unos días y he estado basando la mayor parte de lo que sé de los operadores Java y lambda. Desafortunadamente, realmente no tengo tiempo para sentarme y realmente aprender a Scala como desearía. Plazos, nos hacen el tonto a todos.

Espero que alguien pueda echar un vistazo y decirme si hay algo que estoy haciendo mal (como estoy seguro de que hay). Traté de limitar el código mostrado, lo que espero, sea relevante para la pregunta. Sin embargo, avíseme si se necesita algún código adicional.

Gracias

+0

Supongo que debería dejar en claro que lo anterior es parte de una declaración de comprensión. El 'if (cond)' se supone que es para determinar la ejecución del bloque de rendimiento. He editado mi respuesta para elaborar más sobre el código. – Cowan

Respuesta

1

El xml es una distracción aquí. El problema es si if (cond) al final no está actuando como guardia, simplemente parece que debería, el compilador cree que es el comienzo de una nueva parte si 'entonces'.

En el siguiente ejemplo:

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

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

que obtendrá la lista (6,8,10) como se podría esperar.

Usando

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

debe conseguir que una advertencia de desaprobación, y

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

obtiene

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

Simplemente quite el val delante de su generador (Patrón1 '< -' Expr [Guardia]), y puede reanudar el servicio normal. También fluye un poco más agradable sin los vals en el bucle for que encuentro.

+0

Esta es la mejor respuesta relacionada directamente con la pregunta. Desafortunadamente, esto me hizo volver a pensar el problema y hacer una reescritura significativa. – Cowan

0

if (cond) debe ser seguido por una expresión. En Scala, if es más como el operador ternario en Java: es una expresión, no una declaración. Una declaración de variable no es una expresión (como en Java), por lo que no puede tener un val en la parte then de un if.

Honestamente, no puedo adivinar lo que quiere lograr allí, así que no puedo sugerir una alternativa sintácticamente correcta que tenga sentido. Pero si usted tiene más lógica que depende de cond, usted podría ponerlo en un bloque:

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

Gracias por la respuesta concisa. Olvidé que la declaración if puede actuar como el operador condicional. Sin embargo, en este caso estoy usando la sentencia if como parte de una operación integral, que creo (podría estar muy equivocado) la cambia de un operador ternario a un requisito condicional para la declaración de rendimiento. He revisado mi pregunta anterior para incluir más código. – Cowan

3

En primer lugar, tenga en cuenta que no habrá (row \ "ResultDetectionConditionText")null si no hay niños con ese nombre existen, sólo será un NodeSeq vacío (el código de Scala idiomático tiende a evitar devolver null, como probablemente haya notado). Por lo tanto, su código actual siempre devolverá un Some, que probablemente no sea lo que usted desea. Cambiar su != null a .nonEmpty solucionará ese problema.

A continuación, he aquí una forma más concisa de la escritura de su lógica condicional:

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

Esta dice: obtener una NodeSeq que contiene todos los niños nombrados "Result...", si es que existen, y luego comprobar que NodeSeq para un nodo que contiene el texto "non-detect". La lógica no es exactamente la misma que la tuya, ya que revisamos el texto de los nodos individualmente, pero realmente encaja con lo que supongo que es tu intención aún mejor: presumiblemente no quieres que algo como esto pase la prueba:

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

Pero lo hará en su versión actual.

Pero nada de esto resuelve su problema "illegal start of simple expression"; simplemente corrige la lógica y corta dieciséis líneas de código hasta tres. El problema aquí es que debe decidir cuál debería ser su name si falla la prueba que acaba de realizar.El enfoque más obvia es utilizar un Option:

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

Pero dependiendo de cómo se está utilizando name, algún otro enfoque puede ser más apropiado.

+0

Gracias por la respuesta y señalando esos problemas, aplicaré esos cambios al código. He editado mi pregunta para señalar que todo esto es exhaustivo, por lo que creo (podría estar equivocado) que cambia la naturaleza ternaria de la declaración if. – Cowan

Cuestiones relacionadas