2010-06-16 18 views
13

Jaki jest najprostszy interfejs API do użycia w scala do wykonywania następujących zapytań XPath w dokumencie?Wykonywanie skomplikowanych zapytań XPath w 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 jest zdefiniowany jako pseudonim dla danej przestrzeni nazw)

Jedynym dokumentację można znaleźć na bibliotekach XML Scala zawiera żadnych informacji na temat wykonywania skomplikowanych zapytań XPath rzeczywistym.

Kiedyś lubiłem JDOM w tym celu (w Javie), ale ponieważ JDOM nie obsługuje generycznych, praca z Scala będzie bolesna. (Inne biblioteki XML dla Javy mają tendencję do być jeszcze bardziej bolesne w Javie, ale muszę przyznać, że nie wiem, krajobraz naprawdę dobrze.)

+0

Co czy 's: ...' znaczy? Zakładam, że jest on powiązany z przestrzeniami nazw, ale nie mogłem tego znaleźć w specyfikacji XPath. –

+0

Tak, to prefiks przestrzeni nazw. Zobacz akapit od drugiego do ostatniego wprowadzenia, w którym jest napisane: "W następującej gramatyce nie-terminala QName i NCName są zdefiniowane w [XML Names], a S jest zdefiniowane w [XML]." Wyrażenie 's: Adnotacja' to nazwa QName. –

Odpowiedz

3

Myślę, że pójdę z lekkim sapaniem XOM. To trochę szkoda, że ​​autorzy XOM zdecydowali się nie ujawniać kolekcji węzłów potomnych i tym podobnych, ale mieli więcej pracy i mniejszą przewagę nad tym w Javie niż w Scali. (I to jest inaczej dobrze zaprojektowane biblioteka).

EDIT: I skończyłem stręczycielstwo JDOM po wszystkim, bo XOM nie kompiluje kwerend XPath z wyprzedzeniem. Ponieważ większość moich wysiłków była skierowana na XPath, udało mi się wymyślić dobry model, który rozwiązuje większość problemów związanych z rodzajami leków. Nie powinno być zbyt trudno wymyślić rozsądnie generycznych wersji metod getChildren i getAttributes i getAdditionalNamespaces w org.jdom.Element (przez sfor- mułowanie biblioteki nowymi metodami, które mają lekko zmienione nazwy). Nie sądzę, że istnieje poprawka dla getContent, i nie jestem pewien o getDescendants.

+0

Wysłałem pełny kod mojego opakowania JDOM na http: // stackoverflow. com/questions/4228149/is-there-a-way-to-perform-a-xpath-string-query-using-scalas-xml-library/4228822 # 4228822 –

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

Cóż, ja nie rozumieją notacji s: i mogłam znaleźć go na specyfikacji XPath. Jednakże, nie zważając, że będzie to wyglądać tak:

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

Uwaga konieczność nawiasie powodu wyższego pierwszeństwa \ nad filter. Zmieniłem formatowanie na wyrażenie wielowierszowe, ponieważ odpowiednik Scala jest zbyt rozwlekły dla pojedynczej linii.

Nie mogę jednak odpowiedzieć na temat przestrzeni nazw. Nie ma wskazówki, jak z nimi pracować przy wyszukiwaniu, jeśli jest to nawet możliwe. Dokumenty wymieniają @{uri}attribute dla prefiksowanych atrybutów, nie wspominają nic o prefiksowanych elementach. Zwróć też uwagę, że musisz przekazać URI, który rozwiąże obszar nazw, który chcesz, ponieważ literalne przestrzenie nazw w wyszukiwaniu nie są obsługiwane.

+0

cóż, to brzydkie, ale przynajmniej jest to wykonalne. –

+4

@Ken Wszystkie biblioteki Java są dostępne ... Myślę, że to wstyd nie mieć lepszej obsługi XPath. –

+0

zamiast: (xml \\ Filtr "Adnotacja" (_ \ "@type" zawiera Tekst ("x"))) Użyłbym: (xml \\ "Adnotacja" filtr (x => (x \ "@type"). text == "x")) –

1

Domyślam się, że gdy dojdzie do dojrzałości scalaxmljaxen, będziemy mogli to zrobić niezawodnie na wbudowanych klasach XML scala.

3

Scales Xml dodaje zarówno ciąg oparciu ocenę pełnej XPath oraz wewnętrzny DSL zapewniając dość pełne pokrycie dla zapytań

+0

Nie można znaleźć "pełnego XPath" na podstawie łańcucha znaków , czy czegoś brakuje? –

+0

Zobacz http://scala-scales.googlecode.com/svn/sites/scales/scales-xml_2.9.2/0.4.4/StringXPaths.html na przykład kod – Chris

0

Sugerowałbym użyciu 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") 

Daje:

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