2010-06-16 3 views
13

API đơn giản nhất để sử dụng trong scala để thực hiện các truy vấn XPath sau trên tài liệu là gì?Thực hiện các truy vấn XPath phức tạp trong Scala

//s:Annotation[@type='attitude']/s:Content/s:Parameter[@role='type' and not(text())] 

//s:Annotation[s:Content/s:Parameter[@role='id' and not(text())]]/@type 

(s được định nghĩa là một biệt hiệu cho một không gian tên cụ thể)

Các tài liệu duy nhất mà tôi có thể tìm thấy trên các thư viện XML của Scala không có thông tin về việc thực hiện các truy vấn XPath thực phức tạp.

Tôi đã từng thích JDOM cho mục đích này (bằng Java), nhưng vì JDOM không hỗ trợ Generics, sẽ rất khó để làm việc với Scala. (Thư viện XML khác cho Java có xu hướng thậm chí còn đau đớn hơn trong Java, nhưng tôi thừa nhận tôi không biết cảnh quan thật tốt.)

+0

gì 's: ...' có nghĩa là gì? Tôi cho rằng nó liên quan đến các không gian tên, nhưng tôi không thể tìm thấy nó trong đặc tả XPath. –

+0

Vâng, đó là tiền tố không gian tên. Xem đoạn thứ hai-đến-cuối của phần giới thiệu, nơi nó nói "Trong ngữ pháp sau đây, các phi-terminal QName và NCName được định nghĩa trong [XML Names], và S được định nghĩa trong [XML]." Biểu thức 's: Annotation' là một QName. –

Trả lời

3

Tôi nghĩ rằng tôi sẽ đi với pimping nhẹ XOM. Đó là một chút xấu hổ mà các tác giả XOM đã quyết định chống lại việc trưng ra các bộ sưu tập của các nút con và tương tự, nhưng chúng có nhiều công việc hơn và ít lợi thế hơn để làm như vậy trong Java hơn là trong Scala. (Và nó là một thư viện được thiết kế tốt khác.)

EDIT: Tôi đã sửa đổi trước khi JDOM không biên dịch các truy vấn XPath. Vì hầu hết nỗ lực của tôi hướng đến XPath lần này, tôi đã có thể đưa ra một mô hình tốt để tránh được hầu hết các vấn đề về generics. Không nên quá khó để đưa ra các phiên bản hợp lý hóa hợp lý của các phương pháp getChildrengetAttributesgetAdditionalNamespaces trong org.jdom.Element (bằng cách bung thư viện bằng các phương pháp mới có tên hơi thay đổi.) Tôi không nghĩ rằng có một sửa chữa cho getContent, và tôi không chắc chắn về getDescendants.

+0

Tôi đã đăng toàn bộ mã của trình bao bọc JDOM của tôi tại http: // stackoverflow. com/questions/4228149/is-there-a-way-to-perform-a-xpath-string-truy vấn-sử dụng-scalas-xml-library/4228822 # 4228822 –

12
//s:Annotation[@type='attitude']/s:Content/s:Parameter[@role='type' and not(text())] 

Vâng, tôi không hiểu được s: ký hiệu, và couldn không tìm thấy nó trên spec XPath. Tuy nhiên, bỏ qua rằng điều này sẽ trông như thế này:

(
    (xml 
    \\ "Annotation" 
    filter (_ \ "@type" contains Text("x")) 
) 
    \ "Content" 
    \ "Parameter" 
    filter (el => (el \ "@type" contains Text("type")) && el.isInstanceOf[Text]) 
) 

Lưu ý sự cần thiết phải ngoặc vì ưu tiên cao hơn \ qua filter. Tôi đã thay đổi định dạng thành một biểu thức nhiều dòng vì tương đương Scala chỉ là quá dài dòng cho một dòng.

Tôi không thể trả lời về không gian tên. Không có đầu mối làm thế nào để làm việc với họ trên các tìm kiếm, nếu nó thậm chí có thể. Các tài liệu đề cập đến @{uri}attribute cho các thuộc tính có tiền tố, không đề cập đến bất kỳ điều gì về các phần tử có tiền tố. Ngoài ra, lưu ý rằng bạn cần phải chuyển một uri để giải quyết không gian tên bạn muốn, vì không gian tên theo nghĩa đen trong tìm kiếm không được hỗ trợ.

+0

tốt, đó là xấu xí nhưng ít nhất là nó có thể thực hiện được. –

+4

@Ken Tất cả các thư viện của Java đều có sẵn ... Tôi nghĩ thật đáng tiếc là không hỗ trợ XPath tốt hơn. –

+0

thay vì: (bộ lọc xml \\ "Chú thích" (_ \ "@type" chứa Văn bản ("x"))) Tôi sẽ sử dụng: (bộ lọc xml \\ "Chú thích" (x => (x \ "@type"). văn bản == "x")) –

1

Tôi đoán khi scalaxmljaxen hoàn thiện, chúng tôi sẽ có thể thực hiện điều này một cách đáng tin cậy trên các lớp XML tích hợp của Scala.

3

Scales Xml thêm cả chuỗi dựa đánh giá đầy đủ XPath và một DSL nội bộ cung cấp một phạm vi khá hoàn chỉnh cho các truy vấn

+0

Không thể tìm thấy ví dụ "chuỗi XPath đầy đủ dựa trên" , tui bỏ lỡ điều gì vậy? –

+0

Vui lòng xem http://scala-scales.googlecode.com/svn/sites/scales/scales-xml_2.9.2/0.4.4/StringXPaths.html để biết mã ví dụ – Chris

0

tôi sẽ đề nghị sử dụng kantan.xpath:

import kantan.xpath._ 
import kantan.xpath.implicits._ 

input.evalXPath[List[String]](xp"/annotation[@type='attitude']/content/parameter[@role='type' and not(text())]/@value") 

sản lượng này:

res1: kantan.xpath.XPathResult[List[String]] = Success(List(foobar))