#xslt #xslt-1.0
#xslt #xslt-1.0
Вопрос:
У меня есть XML-файл, подобный этому:
<root>
<node ID="1" />
<node ID="2" />
<node ID="3" />
<node ID="4" />
<node ID="5" />
<node ID="6" />
<node ID="7" get="1" />
<node ID="8" get="1 amp; 3" />
<node ID="9" get="(2 | 23) amp; 3" />
<node ID="10" get="((2 | 3) amp; 1) amp; 15" />
</root>
Проигнорируйте первые 6 узлов на секунду. Мой XSLT обрабатывает узлы 7-10. То, что я хочу сделать, это «обработать» «get» как формулу, чтобы получить true или false в зависимости от того, существует ли узел и формула. amp;
есть logical and
и |
есть logical or
.
Так, например:
- узел 7 XSLT вернет true, поскольку узел 1 существует
- узел 8 XLST вернет true, поскольку существуют как узел 1, так и узел 3
- узел 9 вернет true, потому что узел 2 и узел 3 существуют (даже если узел 23 не существует из-за
or
- узел 10 вернет false, поскольку узел 15 не существует
Можно ли в любом случае сделать что-то подобное с чистым XSLT 1.0?
Если это имеет значение, я могу изменить формат get
значения, если есть какой-то другой формат, который облегчит выполнение того, что я хочу.
Я предполагаю, что должно произойти то, что я отправляю значение get
для каждого узла, который я хочу проверить (в данном случае 7-10), в функцию, которая «обработает» формулу и вернет true или false.
Комментарии:
1. Вам нужно переосмыслить свои требования, прежде чем спрашивать о программировании: имя
get
атрибута предполагает извлечение , а использование логических соединителей предполагает логическую оценку . Что это? Ваши примеры предполагают извлечение, но отрицают логическую природуand
, рассматривая его как простой разделитель для извлекаемых элементов; кроме того, ваши примеры игнорируют логическиеor
— как бы вы «получили»2 | 4
?2. Имя параметра
get
может быть любым. Я просто назвал этоget
для простоты. Идея заключается в том, что XSLT в настоящее время просматривает узел 7. Он будет использовать формулу вget
параметре для извлечения узлов на основе их значения ID. Я обновил пример для узла 7, чтобы дать лучшую идею.3. Вы все еще не указали, как вы хотели бы «получить»
2 | 4
иначе, чем2 amp; 4
.4. XSLT 1.0 (или 2.0) не может вычислить строку как выражение, даже если строка была в допустимом синтаксисе XPath (в отличие от ваших строк). Некоторые процессоры поддерживают
evaluate()
функцию расширения. Без этого вам пришлось бы делать это за два прохода, где первый проход сгенерировал бы таблицу стилей XSLT.5. Как бы вы выразили » получить узлы с идентификаторами 2 И 4 » в XPath?
Ответ №1:
Если это имеет значение, я могу изменить формат
get
значения, если есть какой-то другой формат, который облегчит выполнение того, что я хочу.
Ну, если вы переформатируете get
значение так, чтобы:
- логическое И записывается как
and
; - логическое ИЛИ записывается как
or
; - каждый узел называется как
node[@ID=N]
, а не просто его идентификационный номер,
чтобы ваш входной XML на самом деле выглядел так:
XML
<root>
<node ID="1" />
<node ID="2" />
<node ID="3" />
<node ID="4" />
<node ID="5" />
<node ID="6" />
<node ID="7" get="node[@ID=1]" />
<node ID="8" get="node[@ID=1] and node[@ID=3]" />
<node ID="9" get="(node[@ID=1] or node[@ID=23]) and node[@ID=3]" />
<node ID="10" get="((node[@ID=2] or node[@ID=1]) and node[@ID=1]) and node[@ID=15]" />
</root>
затем вы можете применить следующую таблицу стилей:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:axsl="http://www.w3.org/1999/XSL/TransformAlias">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:namespace-alias stylesheet-prefix="axsl" result-prefix="xsl"/>
<xsl:template match="/root">
<axsl:stylesheet version="1.0">
<axsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<axsl:template match="/root">
<output>
<xsl:for-each select="node[@get]">
<result ID="{@ID}">
<axsl:value-of select="boolean({@get})"/>
</result>
</xsl:for-each>
</output>
</axsl:template>
</axsl:stylesheet>
</xsl:template>
</xsl:stylesheet>
чтобы получить этот результат:
<?xml version="1.0" encoding="UTF-8"?>
<axsl:stylesheet xmlns:axsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<axsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<axsl:template match="/root">
<output>
<result ID="7">
<axsl:value-of select="boolean(node[@ID=1])"/>
</result>
<result ID="8">
<axsl:value-of select="boolean(node[@ID=1] and node[@ID=3])"/>
</result>
<result ID="9">
<axsl:value-of select="boolean((node[@ID=1] or node[@ID=23]) and node[@ID=3])"/>
</result>
<result ID="10">
<axsl:value-of select="boolean(((node[@ID=2] or node[@ID=1]) and node[@ID=1])and node[@ID=15])"/>
</result>
</output>
</axsl:template>
</axsl:stylesheet>
Этот результат является действительной таблицей стилей XSLT. Применение его к вашему входному XML-файлу приведет к следующему результату:
<?xml version="1.0" encoding="UTF-8"?>
<output>
<result ID="7">true</result>
<result ID="8">true</result>
<result ID="9">true</result>
<result ID="10">false</result>
</output>
Комментарии:
1. Что ж, это блестяще. Большое вам спасибо!