обработайте сложные условные проверки с помощью XSLT 1.0

#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 значение так, чтобы:

  1. логическое И записывается как and ;
  2. логическое ИЛИ записывается как or ;
  3. каждый узел называется как 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. Что ж, это блестяще. Большое вам спасибо!