Выполнение сложных запросов XPath в Scala

Какой самый простой 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, но я признаю, что я не очень хорошо знаю ландшафт.)

Ответы

Ответ 1

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

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

Ответ 2

//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

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

Ответ 4

Я предполагаю, что когда scalaxmljaxen является зрелым, мы сможем надежно сделать это на scala встроенных XML-классах.

Ответ 5

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