2015-08-07 9 views
3

Я работаю со следующим фрагментом XPathXPath неоднозначность

ancestor::contribution[1]/preceding-sibling::contribution[@speaker-reference][1] 

Мои Java приложения (с использованием JDOM для XPath запросов) интерпретирует это по-другому из нашей базы данных Oracle (11g). я был в состоянии решить эту проблему с помощью скобок следующим образом:

(ancestor::contribution[1]/preceding-sibling::contribution[@speaker-reference])[1] 

Таким образом, кажется, что JDOM читает XPath как «первый из всех предыдущих contributions с атрибутом @speaker-reference» в то время как Oracle считает, что «предыдущим contribution с атрибутом @speaker-reference and position()=1 ".

Я на самом деле предполагал первую интерпретацию. Мне интересно, какая из двух интерпретаций правильная в соответствии со спецификацией XPath (не может найти подходящее место для поиска) или спецификация позволяет выражениям быть неоднозначными.

+2

не можете добавить короткий пример XML и показать, что вы ожидаете выбрать, и какие именно JDOM и Oracle на самом деле выбирают. Трудно следовать вашему анализу без примера. – wero

+0

wero is right: существует более чем одна потенциальная причина, по которой две реализации могут отличаться, например.обратное направление оси и приоритет привязки. Без образца XML (с несколькими элементами '') трудно быть уверенным, что ваш анализ того, как работают JDOM и Oracle DB, является правильным и полным или для проверки того, какая реализация неверна. Я почти уверен, что дело не в двусмысленности XPath. – LarsH

+0

См. Также мой вопрос/ответ о том, как обратная ось влияет на значение предикатов позиции: http://stackoverflow.com/a/18524097/423105 – LarsH

ответ

3

Согласно XML Path Language Specification, квадратные скобки оператора [..] имеет приоритет 19, в то время как слэш / имеет приоритет 18. Это означает, что последние квадратные скобки [1] должны быть применены к той части выражения после косой черты /, а не ко всей выражение. Другими словами, интерпретация Oracle верна.

Внедрение Java *, которое дает правильный результат без круглых скобок вокруг выражения /, не соответствует стандарту. Рассмотрите возможность подачи ошибки с кратким примером и объяснение того, что происходит.

* По иронии судьбы, это реализация Oracle также.

3

Учитывая ваше описание, нелегко увидеть, что делают JDOM и Oracle. Но их различное поведение, по-видимому, связано с другой реализацией proximity position обратной оси.

Поскольку ancestor::contribution[1] вычисляется в пустой набор узлов или один узел, мы можем упростить пример следующую ситуацию, используя элемент x в качестве узла контекста:

<doc> 
    <contribution speaker-reference="a"/> 
    <contribution speaker-reference="b"/> 
    <contribution/> 
    <x/> 
</doc> 

Выбор preceding-sibling::contribution[speaker-reference] возвращает два взносов узлов с speaker-reference атрибут в заказе.

Выбор (preceding-sibling::contribution[speaker-reference])[1] возвращает первый из этих двух узлов, который является одним из speaker-reference = a.

Выбор preceding-sibling::contribution[speaker-reference][1] предикат позиции [1] должен теперь интерпретироваться в соответствии с порядком оси. Поскольку preceding-sibling является обратной осью, выбранный набор узлов должен обрабатываться в обратном порядке документа. Первой позицией в этом наборе узлов является узел с speaker-reference = b.

Надеюсь, это позволит вам уточнить, какая реализация получила право.

+2

Я согласен. У меня возникли проблемы с разработкой описания, реализация которого имеет ошибку, но правильная интерпретация заключается в том, что 'ancestor :: A [1]/before-sibling :: x [1]' выбирает последний соответствующий элемент в порядке документа, тогда как '(ancestor :: A [1]/before-sibling :: x) [1]' выбирает первый соответствующий элемент в порядке документа. –

Смежные вопросы