#xslt #xpath
#xslt #xpath
Вопрос:
У меня есть набор узлов «file» с атрибутом type
<files>
<file type="main">asdf</file>
<file type="main_en">asdf</file>
<file type="main_fr">asdf</file>
<file type="pdf">asdf</file>
</files>
Как мне проверить на наборе файлов, имеет ли один из узлов хотя бы 1 атрибут, начинающийся с «main».
Я думал что-то вроде:
<xsl:when test="contains(string(files/file[@type]),'main')">
Но все известные мне функции или тесты, похоже, предназначены только для определенного узла, а не для набора узлов.
Я бы предпочел избежать использования решения a для каждого типа.
Ответ №1:
Как мне проверить на наборе файлов, имеет ли один из узлов хотя бы 1 атрибут, начинающийся с «main».
Использовать:
boolean(/*/file[@*[starts-with(., 'main')]])
Это вычисляется true()
точно, когда есть хотя бы один file
элемент, который является дочерним элементом верхнего элемента XML-документа и который имеет хотя бы один атрибут, строковое значение которого начинается со строки "main"
При использовании в test
атрибуте ( <xsl:if>
или <xsl:when>
) или в качестве предиката ссылка на boolean()
функцию необязательна и может быть опущена:
/*/file[@*[starts-with(., 'main')]]
Комментарии:
1. По какой-то причине он возвращает false, когда я пытаюсь это сделать.
2. Я подумал, есть ли способ, которым я мог бы объединить все типы с разделителем в переменную и просто выполнить contains($var,’main’). Но я не уверен, как это сделать.
3. Да, я использовал fn: starts-with вместо starts-with .. не думал, что это что-то изменит. Спасибо 🙂
4. @Jaycuse: Рад, что вы нашли причину своей проблемы. Может быть, пришло время подумать о том, чтобы принять лучший ответ? 🙂
Ответ №2:
<xsl:when test="files/file[contains(@type, 'main')]">
Или, еще лучше:
<xsl:when test="files/file[starts-with(@type, 'main')]">
Комментарии:
1. Хм, не знаю, как за это проголосовали… Я проверял имя атрибута вместо его значения! Исправление.
2. Я попробовал это, и это выдало мне эту ошибку: java.lang. Исключение NoSuchMethodException: для функции расширения не удалось найти метод org.apache.xpath.objects. XNodeSet.StartsWith([ExpressionContext,] #СТРОКА).
3. Интересно — я понятия не имею, почему вы получили эту ошибку, но после просмотра xpath, который был результатом моего первого исправления, это все еще было немного сложно. Я только что исправил это, но понятия не имею, устранит ли это описанную вами ошибку — боюсь, у меня нет среды Xalan для игры.
4. По сравнению с ответом Димитра было бы то, что добавление / перед файлами сделало бы его таким же, за исключением более конкретного. И это работает, но по какой-то причине возвращает false .
<xsl:when test="/files/file[starts-with(@type, 'main')]">
5. О .. это была моя ошибка.. Я использовал fn: starts-with против starts-with .. не думал, что это что-то изменит. Спасибо 🙂
Ответ №3:
Не знаете своей реальной цели, но этот пример может вам помочь:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/files">
<xsl:if test="file[contains(@type,'main')]">
There is at least one file element with 'main' in @type
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Комментарии:
1. В конце концов, я просто хочу, чтобы код в if выполнялся один раз. Вот почему я хочу избежать a для каждого. Потому что он будет выполняться 3 раза. Вроде как, если есть хотя бы один основной файл. Сделайте это один раз, в противном случае сделайте это один раз.