Здравствуйте, Аноним, Вы писали:
А>Хочу на выходе получить: item1:123 item2:32 (уникальные значения src в каждом items)
А>а получаю: item1:123 item2:
А>что не так?
функция key возвращает все узлы документа, удовлетворяюшие словию, а не только детей текущего контекста.
Re[2]: [xslt] Непонятка с xsl:key
От:
Аноним
Дата:
30.01.12 14:30
Оценка:
Здравствуйте, Lloyd, Вы писали:
L>функция key возвращает все узлы документа, удовлетворяюшие словию, а не только детей текущего контекста.
Я не против), но не понимаю... почему в первом вызове ComplexTemplate он что-то (и похоже правильно печатает), во втором — не печает ничего. Что мзменилось кроме текущего узла?
Re[2]: [xslt] Непонятка с xsl:key
От:
Аноним
Дата:
30.01.12 14:36
Оценка:
Здравствуйте, Lloyd, Вы писали:
L>функция key возвращает все узлы документа, удовлетворяюшие словию, а не только детей текущего контекста.
Нужно в коллекцию srcKeys в uses добавить идентификатор родительского items. Я в правильную сторону думаю?
Здравствуйте, Аноним, Вы писали:
L>>функция key возвращает все узлы документа, удовлетворяюшие словию, а не только детей текущего контекста.
А>Я не против), но не понимаю... почему в первом вызове ComplexTemplate он что-то (и похоже правильно печатает), во втором — не печает ничего. Что мзменилось кроме текущего узла?
Ваш код выводит все те узлы внутри <items name="item1"> и <items name="item2"> соответственно, которые являются первыми в порядке появления в документе среди узлов с таким же занчением атрибута src.
Если вы внимательно посмотрите код, то увидите, что такие узлы присутствуют только в <items name="item1">.
Добавьте в куда-нить внутрь <items name="item1"> узел <item src="666" value="xxx"/> и вы увидите, что и во втором выводе появится результат.
Re[4]: [xslt] Непонятка с xsl:key
От:
Аноним
Дата:
30.01.12 14:42
Оценка:
Здравствуйте, Lloyd, Вы писали:
L>Ваш код выводит все те узлы внутри <items name="item1"> и <items name="item2"> соответственно, которые являются первыми в порядке появления в документе среди узлов с таким же занчением атрибута src.
Здравствуйте, Аноним, Вы писали:
L>>функция key возвращает все узлы документа, удовлетворяюшие словию, а не только детей текущего контекста.
А>Нужно в коллекцию srcKeys в uses добавить идентификатор родительского items. Я в правильную сторону думаю?
Не совсем. По сути ошибка у вас в предикате "generate-id()= generate-id(key('srcKeys', @src))", его и надо править.
generate-id в правой части в том виде, как он есть, вернет id первого соответствующего элемента во всем документе. Вам же нужно чтобы просматривались только элементы текущего контекста, поэтому нужно выбросить из множества элементов, возвращаемых key-ем те, что не являются детьми. Для этого справа после key нужно приписать предикат, который такие узлы отбросит.
Попозже постараюсь набросать, что получится. Пока времени нет.
Здравствуйте, Аноним, Вы писали:
L>>функция key возвращает все узлы документа, удовлетворяюшие словию, а не только детей текущего контекста.
А>Нужно в коллекцию srcKeys в uses добавить идентификатор родительского items. Я в правильную сторону думаю?
Нужно вот так переписать второй шалон, тогда будет работать так, как вы ожидаете:
Поскольку generate-id с nodeset-ом в аргументе равнозначен generate-id(nodeset[1]), то вызов ключа для потомков items2 будет находить элементы из items2 только в том случае, если элементов с соответствующим src нет в items1 (document order и все такое), а поскольку они там есть, то мы имеем то, что имеем. В данном случае можно делать составной ключ — use="concat(ancestor::items/@name, '|', @src)" — это даст возможность использовать ключ в нужном контексте.
Здравствуйте, Аноним, Вы писали:
А>Поскольку generate-id с nodeset-ом в аргументе равнозначен generate-id(nodeset[1]), то вызов ключа для потомков items2 будет находить элементы из items2 только в том случае, если элементов с соответствующим src нет в items1 (document order и все такое), а поскольку они там есть, то мы имеем то, что имеем. В данном случае можно делать составной ключ — use="concat(ancestor::items/@name, '|', @src)" — это даст возможность использовать ключ в нужном контексте.
Не надо этого делать, это плохой подход — завтра у вас окажется, что items встречается палка в атрибуте name и все, приплыли.
Правильный подход описан двумя постами ниже.
Здравствуйте, Lloyd, Вы писали:
L>Здравствуйте, Аноним, Вы писали:
А>>Поскольку generate-id с nodeset-ом в аргументе равнозначен generate-id(nodeset[1]), то вызов ключа для потомков items2 будет находить элементы из items2 только в том случае, если элементов с соответствующим src нет в items1 (document order и все такое), а поскольку они там есть, то мы имеем то, что имеем. В данном случае можно делать составной ключ — use="concat(ancestor::items/@name, '|', @src)" — это даст возможность использовать ключ в нужном контексте.
L>Не надо этого делать, это плохой подход — завтра у вас окажется, что items встречается палка в атрибуте name и все, приплыли. L>Правильный подход описан двумя постами ниже.
Насчет имени и палки вы правы, но это не значит, что сам тема составных ключей плоха, просто их надо использовать с умом, вот и все.
По теме: use="concat(generate-id(ancestor::items), '|', @src)". По спецификации generate-id не вернет палку, так что generate-id + | + str — всегда однозначно определенный идентификатор элемента с палкой и с какой-то строкой на конце.
Здравствуйте, hredwolf, Вы писали:
L>>Не надо этого делать, это плохой подход — завтра у вас окажется, что items встречается палка в атрибуте name и все, приплыли. L>>Правильный подход описан двумя постами ниже.
H>Насчет имени и палки вы правы, но это не значит, что сам тема составных ключей плоха, просто их надо использовать с умом, вот и все. H>По теме: use="concat(generate-id(ancestor::items), '|', @src)". По спецификации generate-id не вернет палку, так что generate-id + | + str — всегда однозначно определенный идентификатор элемента с палкой и с какой-то строкой на конце.
Использовать составные ключи для этой задачи можно, но не нужно. Если есть более прямые пути, то надо спользовать их.
Здравствуйте, Lloyd, Вы писали:
L>Здравствуйте, hredwolf, Вы писали:
L>>>Не надо этого делать, это плохой подход — завтра у вас окажется, что items встречается палка в атрибуте name и все, приплыли. L>>>Правильный подход описан двумя постами ниже.
H>>Насчет имени и палки вы правы, но это не значит, что сам тема составных ключей плоха, просто их надо использовать с умом, вот и все. H>>По теме: use="concat(generate-id(ancestor::items), '|', @src)". По спецификации generate-id не вернет палку, так что generate-id + | + str — всегда однозначно определенный идентификатор элемента с палкой и с какой-то строкой на конце.
L>Использовать составные ключи для этой задачи можно, но не нужно. Если есть более прямые пути, то надо спользовать их.
Не соглашусь. Ключи тут не работают из-за того, что мы не можем нормально задать контекст поиска, в xslt2 эта проблема решена возможностью указания top node при вызове key, а в xslt1 натуральным способом решения проблемы выглядят составные ключи, что по сути есть handmade эмуляция решения из xslt2. По мне так это точно натуральней и более производительней, чем доп. переменные и трики с count(s)=count(s|a).
Здравствуйте, hredwolf, Вы писали:
L>>Использовать составные ключи для этой задачи можно, но не нужно. Если есть более прямые пути, то надо спользовать их.
H>Не соглашусь. Ключи тут не работают из-за того, что мы не можем нормально задать контекст поиска, в xslt2 эта проблема решена возможностью указания top node при вызове key, а в xslt1 натуральным способом решения проблемы выглядят составные ключи, что по сути есть handmade эмуляция решения из xslt2. По мне так это точно натуральней и более производительней, чем доп. переменные и трики с count(s)=count(s|a).
Не могу согаситься. Решение в с top-ом мне нравится, а вариант с сотавным ключем — совсем нет.
Не нравится это решение мне потому, что оно не напрямую решает эту задачу, в через одно место.
Ведь сама задача звучит так: найти уникальные по заданному атрибуту элементы item внутри заданного контекста.
Ваше решение для этого вводит искуственное понятие составного ключа, которое приписывается каждому элементу в item в документе и потом этот ключ уже и используется.
У такого решения просматриваются как минимум 2 недостатка:
1. код по решению задачи размазывается по всему документу (для решения локальной задачи вводим глобальный ключ, сформированный специальным образом)
2. ваш код очень легко ломается, если внутри items, что вы обрабатываем оказываются и другие дочерние items и универсального решения не просматривается вовсе.
Мой же вариант прямой как палка и один-в-один ложится на формулировку задачи:
.//item[@src and generate-id()= generate-id(key('srcKeys', @src)[count($items) = count($items|.)])]
1. Взять все item текущего узла (.//item)
2. Для каждого item-а из найти все узлы item с таким же значением атрибута src (key('srcKeys', @src))
3. Из этого набора оставить только узлы, которые являются детьми ткущего item-а ([count($items) = count($items|.)])
4. Проверить, что текущий item является первым в полученном наборе (generate-id(.) = generate-id(...))
Тут единственная сложность, которая может возникнуть — это 3-й пункт. Тут согласен, в xpath-е нет нормальных функций по проверке вхождения элемента во множество, приходится изворачиваться таким способом.
В таких условиях да, могут быть проблемы, но если условия такие, как в задаче и меняться не собираются, то почему нет? А на будущее я бы предложил вариант перехода на xslt2.0, тогда уйдет огроменная масса проблем, решаемая обычно с помощью всяких хаков.
Здравствуйте, Lloyd, Вы писали:
L>Здравствуйте, hredwolf, Вы писали:
L>>>Использовать составные ключи для этой задачи можно, но не нужно. Если есть более прямые пути, то надо спользовать их.
H>>Не соглашусь. Ключи тут не работают из-за того, что мы не можем нормально задать контекст поиска, в xslt2 эта проблема решена возможностью указания top node при вызове key, а в xslt1 натуральным способом решения проблемы выглядят составные ключи, что по сути есть handmade эмуляция решения из xslt2. По мне так это точно натуральней и более производительней, чем доп. переменные и трики с count(s)=count(s|a).
L>Не могу согаситься. Решение в с top-ом мне нравится, а вариант с сотавным ключем — совсем нет.
L>Не нравится это решение мне потому, что оно не напрямую решает эту задачу, в через одно место. L>Ведь сама задача звучит так: найти уникальные по заданному атрибуту элементы item внутри заданного контекста.
L>Ваше решение для этого вводит искуственное понятие составного ключа, которое приписывается каждому элементу в item в документе и потом этот ключ уже и используется. L>У такого решения просматриваются как минимум 2 недостатка: L> 1. код по решению задачи размазывается по всему документу (для решения локальной задачи вводим глобальный ключ, сформированный специальным образом) L> 2. ваш код очень легко ломается, если внутри items, что вы обрабатываем оказываются и другие дочерние items и универсального решения не просматривается вовсе.
L>Мой же вариант прямой как палка и один-в-один ложится на формулировку задачи: L>.//item[@src and generate-id()= generate-id(key('srcKeys', @src)[count($items) = count($items|.)])] L> 1. Взять все item текущего узла (.//item) L> 2. Для каждого item-а из найти все узлы item с таким же значением атрибута src (key('srcKeys', @src)) L> 3. Из этого набора оставить только узлы, которые являются детьми ткущего item-а ([count($items) = count($items|.)]) L> 4. Проверить, что текущий item является первым в полученном наборе (generate-id(.) = generate-id(...))
L>Тут единственная сложность, которая может возникнуть — это 3-й пункт. Тут согласен, в xpath-е нет нормальных функций по проверке вхождения элемента во множество, приходится изворачиваться таким способом.
Здравствуйте, hredwolf, Вы писали:
H>В таких условиях да, могут быть проблемы, но если условия такие, как в задаче и меняться не собираются, то почему нет?
Если есть решение, которое не хуже, а по некоторым параметрам и лучше, то почему бы не сипользовать его?
H>А на будущее я бы предложил вариант перехода на xslt2.0, тогда уйдет огроменная масса проблем, решаемая обычно с помощью всяких хаков.
Не на всех платформах он есть из каробки (.Net, например), а тащить с собой многомегабайтную зависимость да еще и разбираться нет ли каких подводных камней с лицензиями — не всякий на это пойдет. А жаль.