XML: определите переменную оптимальным способом

#xml #xslt #xslt-1.0

Вопрос:

Из одного и того же ввода у меня разные пути для одного и того же элемента (это почти точно тот же путь, за исключением 1 элемента, см. Ниже).

Моя логика зависит от элемента «типология» (определенного в моем коде)

XSLT 1.0

 <xsl:variable name="date">
<xsl:choose>
<xsl:when test="$typology='A' or $typology='B' ">
<xsl:value-of select="/Header/info/data/Body/basketAB/date"/>
</xsl:when>
<xsl:when test="$typology='C' or $typology='D' or $typology='E'">
<xsl:value-of select="/Header/info/data/Body/basketCDE/date"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'CheckPath'"/>
</xsl:otherwise>
</xsl:choose>
 

Как я могу избежать использования choose несколько путей и получить «дату» только с 1 пути.

Ответ №1:

Решите это, определив дату как:

 <xsl:variable name="date" select="//date"/>
 

Ответ №2:

Используйте это единственное выражение XPath 1.0:

 concat(/Header/info/data/Body/basketAB
                               [contains('|A|B|', concat('|', $typology, '|'))]/date
     | /Header/info/data/Body/basketCDE
                              [contains('|C|D|E|', concat('|', $typology, '|'))]/date,
       substring('CheckPath', 
                 1 div not(contains('|A|B|C|D|E|', concat('|', $typology, '|'))))
      )
 

Проверка с помощью XSLT 1.0:

Учитывая этот исходный XML-документ:

 <Header>
  <info>
    <data>
        <Body>
          <basketAB>
             <date>date1</date>
          </basketAB>
          <basketCDE>
             <date>date2</date>
          </basketCDE>
        </Body>
    </data>
  </info>
</Header>
 

это преобразование XSLT оценивает приведенное выше выражение XPath и выводит результат этой оценки:

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:variable name="typology" select="'A'"/>

  <xsl:template match="/">
    <xsl:variable name="date" select=
      "concat(/Header/info/data/Body/basketAB[contains('|A|B|', concat('|', $typology, '|'))]/date
            | /Header/info/data/Body/basketCDE[contains('|C|D|E|', concat('|', $typology, '|'))]/date,
              substring('CheckPath', 1 div not(contains('|A|B|C|D|E|', concat('|', $typology, '|'))))
              )"/>
    <xsl:value-of select="$date"/>
  </xsl:template>
</xsl:stylesheet>
 

Выполните преобразование несколько раз, каждый раз указывая другое значение переменной $typology :

Желаемые результаты получены во всех случаях:

‘A’ —> дата1

‘B’ —> дата 1


‘C’ —> дата 2

‘D’ —> дата 2

‘E’ —> дата 2


‘X’ —> Контрольная дорожка

Ответ №3:

Я бы избегал оси потомков и использовал более четкий путь:

 <xsl:variable name="date" select="/Header/info/data/Body/*/date"/>
 

Это предполагает, что входные данные не могут содержать оба basketAB basketCDE элемента и (этот момент неясен из вашего вопроса, но в противном случае ни этот, ни принятый в настоящее время ответ не могут работать).


Если приведенное выше предположение окажется неверным, вы могли бы сделать:

 <xsl:variable name="date" select="/Header/info/data/Body/*[contains(name(), $typology)]/date"/>