@neo, выражение XPath вы перечислить не работает, когда я проверить его. Попробуйте другой набор данных, и вы увидите:
<root>
<item>
<d>2003-05-30T09:00:00</d>
</item>
<item>
<d>2002-05-30T09:00:00</d>
</item>
<item>
<d>2005-05-30T09:00:00</d>
</item>
</root>
Ваш XPath производит 2003-05-30T09:00:00
, что, очевидно, не макс.
И имеет смысл, что это не сработает, потому что предыдущие оси sibling :: и follow-sibling :: внутри функций translate() будут давать только один родной друг. Вы пытаетесь перейти к общему (установленному) сравнению со всеми братьями и сестрами на каждой оси, но первый аргумент для перевода() должен быть преобразован в строку, прежде чем у оператора сравнения будет возможность выполнить свою задачу. Converting a nodeset to a string ignores all nodes except the first one in document order.
Кроме того, translate(./d, 'TZ:-', '.')
дает вам результаты, такие как 2003.05.30.09.00.00
. Это не действительное число, за пределами «5». Ваши тестовые данные работают только потому, что годы разные. Вы получите лучшие результаты с translate(./d, 'TZ:-', '')
, который даст 20030530090000
.
Алехандро говорит, что это невозможно в XPath 1.0, и он может быть прав. Попробуем, и, может быть, мы узнаем что-то, даже если нам это не удастся.
Далее я попытался бы использовать общее сравнение вне функции перевода, чтобы он мог сравнивать целые наборы узлов. Что-то вроде этой наивной попытки:
/root/item[
not(following-sibling::item[
translate($current/d, 'TZ:-', '') <= translate(./d, 'TZ:-', '')])
and not(preceding-sibling::item[
translate($current/d, 'TZ:-', '') <= translate(./d, 'TZ:-', '')])]
Однако это является неполным, как показано на псевдо-переменной $ тока, который должен относиться к внешнему пункту, тот, который является узлом контекста вне всех предикатов. К сожалению, XPath 1.0 не дает нам способ ссылаться на этот внешний контекст, когда другой контекст был нажат на стек внутренним предикатом.
(Я, кажется, напоминаю, что \ некоторые реализации XSLT, например MSXML, позволяют сделать это с помощью расширенной функции, например current(1)
, но я не могу найти информацию об этом на данный момент. решение XPath и current()
- не XPath.)
На данный момент я согласен с Алехандро, что это невозможно в чистом стандартном XSLT 1.0.
Если вы укажете среду, в которой вы используете XPath, например. XSLT, Javascript или XQuery, мы можем предложить эффективный способ получить то, что вам нужно. Если это XPath 2.0, у Алехандро есть свой ответ.
Если у вас есть XQuery 1.0, она должна поддерживать XPath 2.0, так что вы можете использовать решение Алехандро, с доком(), чтобы получить доступ к входной XML-документа:
max(doc("myInput.xml")/root/item/d/xs:dateTime(.))
Хорошо работает, мне очень нравится этот синтаксис, см. также мой комментарий к другому ответу. – letmaik
@neo: Я рад, что это вам помогло. Теперь, когда вы знаете, что у вас XQuery 1.0 и XPath 2.0, вы найдете много улучшений от XPath 1.0: в данном случае не только 'fn: max', но и возможность использовать выражения в качестве последнего шага в пути. Также я поставил ваш вопрос. – 2010-08-31 13:22:09