2012-09-06 27 views
5

Tôi đang phân tích cú pháp một chuỗi các phản hồi XML từ một kho lưu trữ dữ liệu ngoài. Trong thời gian đó tôi phải kiểm tra sự tồn tại của một nút con và - nếu nó tồn tại - hãy kiểm tra giá trị của nó. Để đạt được điều đó tôi có đoạn mã sau:Scala XML: kiểm tra sự tồn tại của nút và giá trị

... 
    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 được định nghĩa như vậy:

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

Kết quả mã trên trong một lỗi không xác định "bắt đầu bất hợp pháp của biểu thức đơn giản" trên dòng val name.... Thành thật mà nói tôi không phải là một lập trình viên Scala hoặc thậm chí là một lập trình viên chức năng (luôn luôn là một phần hơn để OO/mệnh lệnh). Tôi đã chỉ được sử dụng Scala cho một vài ngày và được dựa trên hầu hết những gì tôi biết từ các nhà khai thác Java và lambda. Thật không may, tôi không thực sự có thời gian để ngồi xuống và thực sự học Scala như tôi ước mình có thể. Thời hạn, làm cho kẻ ngu của tất cả chúng ta.

Tôi hy vọng rằng ai đó có thể xem và cho tôi biết nếu có điều gì đó tôi đang làm sai (như tôi chắc chắn có). Tôi đã cố gắng giới hạn mã hiển thị, những gì tôi hy vọng, có liên quan đến câu hỏi. Tuy nhiên, vui lòng cho tôi biết nếu có bất kỳ mã bổ sung nào là cần thiết.

Cảm ơn

+0

Tôi đoán tôi nên nói rõ ràng rằng phần trên là một phần của sự hiểu biết về tuyên bố. 'If ​​(cond)' được cho là để xác định việc thực hiện khối lợi nhuận. Tôi đã chỉnh sửa câu trả lời của mình để xây dựng thêm về mã. – Cowan

Trả lời

1

Xml là sự phân tâm ở đây. Vấn đề là nếu (cond) ở cuối là không hoạt động như một người bảo vệ, nó chỉ trông giống như nó nên, trình biên dịch nghĩ là sự khởi đầu của một phần mới nếu 'sau đó'.

Trong ví dụ sau:

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

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

bạn sẽ nhận được danh sách (6,8,10) như bạn mong đợi.

Sử dụng

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

nên giúp bạn có được một cảnh báo không dùng nữa, và

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

được

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

Đơn giản chỉ cần loại bỏ các val trước Generator của bạn (Pattern1 '< -' Expr [Guard]) và bạn có thể tiếp tục dịch vụ thông thường. Nó cũng chảy một chút độc đáo hơn mà không có các vals trong vòng lặp cho tôi tìm thấy.

+0

Đây là câu trả lời hay nhất liên quan trực tiếp đến câu hỏi. Thật không may, điều này khiến tôi phải nghĩ lại vấn đề và viết lại một cách đáng kể. – Cowan

0

if (cond) phải được theo sau bởi một biểu thức. Trong Scala, if giống như toán tử bậc ba trong Java: nó là một biểu thức, không phải là một câu lệnh. Một khai báo biến không phải là một biểu thức (như trong Java), vì vậy bạn không thể có một val trong phần then của một if.

Thành thật mà nói, tôi không thể đoán những gì bạn muốn đạt được ở đó, vì vậy tôi không thể đề xuất một giải pháp thay thế cú pháp chính xác có ý nghĩa. Nhưng nếu bạn có nhiều logic mà phụ thuộc vào cond, bạn có thể đặt nó trong một khối:

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

Cảm ơn bạn đã phản hồi ngắn gọn. Tôi quên rằng câu lệnh if có thể hoạt động như toán tử điều kiện. Tuy nhiên, trong trường hợp này, tôi đang sử dụng câu lệnh if như là một phần của một hoạt động toàn diện, mà tôi tin rằng (tôi có thể bị nhầm lẫn) thay đổi nó từ một toán tử bậc ba thành một yêu cầu có điều kiện cho câu lệnh yield. Tôi đã sửa đổi câu hỏi của mình ở trên để bao gồm nhiều mã hơn. – Cowan

3

Trước hết, lưu ý rằng (row \ "ResultDetectionConditionText") sẽ không null nếu không có con với tên đó tồn tại-nó sẽ chỉ được trống NodeSeq (mã Scala thành ngữ có xu hướng tránh trả lại null, như bạn có thể đã nhận thấy). Vì vậy, mã hiện tại của bạn sẽ luôn trả về Some, có thể không phải là thứ bạn muốn. Thay đổi != null thành .nonEmpty sẽ khắc phục sự cố đó.

Tiếp theo, đây là một cách ngắn gọn hơn viết logic có điều kiện của bạn:

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

này nói: có được một NodeSeq có chứa tất cả những đứa trẻ được đặt tên "Result...", nếu chúng tồn tại, và sau đó kiểm tra xem NodeSeq cho một nút chứa văn bản "non-detect". Logic không chính xác giống như của bạn, vì chúng tôi kiểm tra văn bản của các nút riêng lẻ, nhưng nó thực sự phù hợp với những gì tôi đoán là ý định của bạn thậm chí còn tốt hơn - có lẽ bạn không muốn một cái gì đó như thế này để vượt qua bài kiểm tra:

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

Nhưng nó sẽ có trong phiên bản hiện tại của bạn.

Nhưng không cách nào trong số này giải quyết vấn đề "illegal start of simple expression" của bạn — nó chỉ sửa lỗi và cắt giảm mười sáu dòng mã xuống còn ba. Vấn đề ở đây là bạn cần phải quyết định những gì name của bạn nên được nếu thử nghiệm bạn vừa thực hiện không thành công.Cách tiếp cận dễ nhất là sử dụng một Option:

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

Nhưng tùy thuộc vào cách bạn đang sử dụng name, một số phương pháp khác có thể thích hợp hơn.

+0

Cảm ơn bạn đã phản hồi và chỉ ra những vấn đề đó, tôi sẽ áp dụng những thay đổi đó cho mã. Tôi đã chỉnh sửa câu hỏi của tôi để chỉ ra rằng đây là tất cả trong một toàn diện-mà tôi nghĩ (có thể là sai) thay đổi bản chất ternary của tuyên bố nếu. – Cowan

Các vấn đề liên quan