Выполнение сложных XPath-запросов в Scala - PullRequest
13 голосов
/ 16 июня 2010

Какой самый простой API в scala используется для выполнения следующих XPath-запросов к документу?

//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 определяется как псевдоним для определенного пространства имен)

Единственная документация, которую я могу найти в XML-библиотеках Scala, не содержит информации о выполнении сложных реальных запросов XPath.

Раньше мне нравилось JDOM для этой цели (в Java), но поскольку JDOM не 'Не поддерживая дженерики, работать в Scala будет больно.(Другие библиотеки XML для Java, как правило, были еще более болезненными в Java, но я признаю, что не очень хорошо знаю ландшафт).

Ответы [ 5 ]

12 голосов
/ 17 июня 2010
//s:Annotation[@type='attitude']/s:Content/s:Parameter[@role='type' and not(text())]

Что ж, я не понимаю нотацию s: и не могу найти ее в спецификации XPath. Однако, игнорируя, что это будет выглядеть так:

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

Обратите внимание на необходимость скобок из-за более высокого приоритета \ над filter. Я изменил форматирование на многострочное выражение, поскольку эквивалент Scala слишком многословен для одной строки.

Хотя я не могу ответить о пространствах имен. Понятия не имею, как с ними работать в поисках, если это вообще возможно. Документы упоминают @{uri}attribute для префиксных атрибутов, не упоминает ничего о префиксных элементах. Также обратите внимание, что вам нужно передать uri, который разрешается в нужное вам пространство имен, так как буквенные пространства имен в поиске не поддерживаются.

3 голосов
/ 05 ноября 2011

Scales Xml добавляет как строковую полную оценку XPath, так и внутренний DSL, обеспечивающий достаточно полное покрытие для запросов

3 голосов
/ 17 июня 2010

Я думаю, что я собираюсь пойти с легким сутенерством XOM .Немного обидно, что авторы XOM решили не выставлять коллекции дочерних узлов и тому подобное, но у них было больше работы и меньше преимуществ в Java, чем в Scala.(И в остальном это хорошо спроектированная библиотека.)

РЕДАКТИРОВАТЬ: Я все-таки завел pimping JDOM, потому что XOM не компилирует запросы XPath заранее.Поскольку в этот раз большая часть моих усилий была направлена ​​на XPath, я смог придумать хорошую модель, которая обошла бы большинство проблем дженериков.Не должно быть слишком сложно придумать разумные обобщенные версии методов getChildren и getAttributes и getAdditionalNamespaces в org.jdom.Element (путем добавления в библиотеку новых методов, которые слегка изменили имена).Я не думаю, что есть исправление для getContent, и я не уверен насчет getDescendants.

1 голос
/ 21 июня 2010

Полагаю, когда scalaxmljaxen станет зрелым, мы сможем сделать это надежно с помощью встроенных в Scala XML-классов.

0 голосов
/ 26 октября 2017

Я бы предложил использовать 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")

Это дает:

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