XSL, если условие else

У меня есть требование, когда я хотел бы иметь инструкцию if else, чтобы проверить, имеет ли атрибут node или имеет только строку.

Например: 1 из node имеет 0 File(s) found, а другой имеет атрибуты, такие как <autoincludesystem_info mdate='08/23/2011' mtime='09:51' ampm='PM' filesize='64' filename='AFP_p.tgp' />

Ниже приведен образец из двух узлов

<product>
<autoIncludeUser>0 File(s) found</autoIncludeUser>
<autoIncludeSystem>
<autoincludesystem_info mdate='08/23/2011' mtime='09:51' ampm='PM' filesize='64' filename='AFP_p.tgp' />
<autoincludesystem_info mdate='08/23/2011' mtime='09:51' ampm='PM' filesize='3,879' filename='AnalystsExpressionMacros.tgp' />
<autoincludesystem_info mdate='08/23/2011' mtime='09:51' ampm='PM' filesize='475' filename='base64Converter.tgp' />
<autoincludesystem_info mdate='08/23/2011' mtime='09:51' ampm='PM' filesize='&lt;DIR&gt;' filename='codePages' />
</autoIncludeSystem>
<autoIncludeStudio>0 File(s) found</autoIncludeStudio>
<externalLibrarySystem>
<externalLibrarySystem_info mdate='08/23/2011' mtime='09:52' ampm='PM' filesize='196,608' filename='AFPtoXML_DP.dll' />
<externalLibrarySystem_info mdate='08/23/2011' mtime='09:52' ampm='PM' filesize='13,259' filename='ASN1toXSDRunner.jar' />
<externalLibrarySystem>
</product>

Как бы я определил, имеет ли node только строки или атрибуты, и на основе этого я могу получить значения либо String, либо attrib values соответственно.

Ответ 1

Вы можете заменить всю команду xsl:choose на:

<xsl:apply-templates select="autoIncludeSystem"/>

а затем добавьте два шаблона:

<xsl:template match="autoIncludeSystem[autoincludesystem_info/@*]>
  <!-- code for elements with attributes (xsl:when) -->
</xsl:template>


<xsl:template match="autoIncludeSystem[not(autoincludesystem_info/@*)]>
  <!-- code for elements without attributes (xsl:otherwise) -->
</xsl:template>

Ответ 2

Мы можем достичь, если еще, используя ниже код

<xsl:choose>
    <xsl:when test="something to test">

    </xsl:when>
    <xsl:otherwise>

    </xsl:otherwise>
</xsl:choose>

Итак, вот что я сделал

<h3>System</h3>
    <xsl:choose>
        <xsl:when test="autoIncludeSystem/autoincludesystem_info/@mdate"> <!-- if attribute exists-->
            <p>
                <dd><table border="1">
                    <tbody>
                        <tr>
                            <th>File Name</th>
                            <th>File Size</th>
                            <th>Date</th>
                            <th>Time</th>
                            <th>AM/PM</th>
                        </tr>
                        <xsl:for-each select="autoIncludeSystem/autoincludesystem_info">
                            <tr>
                                <td valign="top" ><xsl:value-of select="@filename"/></td>
                                <td valign="top" ><xsl:value-of select="@filesize"/></td>
                                <td valign="top" ><xsl:value-of select="@mdate"/></td>
                                <td valign="top" ><xsl:value-of select="@mtime"/></td>
                                <td valign="top" ><xsl:value-of select="@ampm"/></td>
                            </tr>
                        </xsl:for-each>
                    </tbody>
                </table>
                </dd>
            </p>
        </xsl:when>
        <xsl:otherwise> <!-- if attribute does not exists -->
            <dd><pre>
                <xsl:value-of select="autoIncludeSystem"/><br/>
            </pre></dd> <br/>
        </xsl:otherwise>
    </xsl:choose>

Мой вывод

enter image description here

Ответ 3

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

concat(substring('String', 1 div boolean(text())),
                 ' ',
       substring('attrib values', 1 div boolean(@*))
       )

Вот проверка на основе XSLT:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="*[not(*)]">
     <xsl:value-of select="concat('&#10;', name(),': ')"/>

     <xsl:value-of select=
      "concat(substring('String', 1 div boolean(text())),
              ' ',
              substring('attrib values', 1 div boolean(@*))
             )
      "/>
 </xsl:template>
</xsl:stylesheet>

, когда это преобразование применяется к предоставленному XML-документу (слегка исправлено, чтобы сделать его корректным):

<product>
    <autoIncludeUser>0 File(s) found</autoIncludeUser>
    <autoIncludeSystem>
        <autoincludesystem_info mdate='08/23/2011' mtime='09:51' ampm='PM' filesize='64' filename='AFP_p.tgp' />
        <autoincludesystem_info mdate='08/23/2011' mtime='09:51' ampm='PM' filesize='3,879' filename='AnalystsExpressionMacros.tgp' />
        <autoincludesystem_info mdate='08/23/2011' mtime='09:51' ampm='PM' filesize='475' filename='base64Converter.tgp' />
        <autoincludesystem_info mdate='08/23/2011' mtime='09:51' ampm='PM' filesize='&lt;DIR&gt;' filename='codePages' />
    </autoIncludeSystem>
    <autoIncludeStudio>0 File(s) found</autoIncludeStudio>
    <externalLibrarySystem>
        <externalLibrarySystem_info mdate='08/23/2011' mtime='09:52' ampm='PM' filesize='196,608' filename='AFPtoXML_DP.dll' />
        <externalLibrarySystem_info mdate='08/23/2011' mtime='09:52' ampm='PM' filesize='13,259' filename='ASN1toXSDRunner.jar' />
    </externalLibrarySystem>
</product>

требуется, правильный результат получается:

autoIncludeUser: String 
autoincludesystem_info:  attrib values
autoincludesystem_info:  attrib values
autoincludesystem_info:  attrib values
autoincludesystem_info:  attrib values
autoIncludeStudio: String 
externalLibrarySystem_info:  attrib values
externalLibrarySystem_info:  attrib values

Объяснение Мы используем следующие факты:

  • Для любой строки $s, substring($s, Infinity) - это пустая строка.

  • 1 div 0 Infinity

  • По определению number(true()) есть 1, а number(false()) равно 0.

    II. Решение XPath 2.0:

Это намного проще в XPath 2.0, потому что язык имеет стандартный if/then/else оператор.

Использование

if(text())
  then 'String'
  else if(@*)
         then 'attrib values'
         else ()

Проверка XSLT 2.0:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="*[not(*)]">
     <xsl:value-of select="concat('&#10;', name(),': ')"/>

     <xsl:value-of select=
      "if(text())
         then 'String'
         else if(@*)
           then 'attrib values'
           else ()
      "/>
 </xsl:template>
</xsl:stylesheet>

, когда это преобразование применяется к одному и тому же документу XML (см. выше), снова получается желаемый, правильный результат:

autoIncludeUser: String
autoincludesystem_info: attrib values
autoincludesystem_info: attrib values
autoincludesystem_info: attrib values
autoincludesystem_info: attrib values
autoIncludeStudio: String
externalLibrarySystem_info: attrib values
externalLibrarySystem_info: attrib values

Ответ 4

XPath //*[not(@*)] выберет все элементы, у которых нет атрибутов.

Ответ 5

Вы можете сделать это достаточно легко, используя xsl:choose - но очень часто в XSLT, лучший способ сделать условную обработку - писать разные правила шаблонов для обработки различных условий. Поэтому напишите одно правило шаблона с помощью match="*[@*]" для соответствия элементам с атрибутами, а другое с match="*[text()]" для соответствия элементам с текстовым контентом.