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='<DIR>' 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(' ', 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='<DIR>' 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(' ', 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()]"
для соответствия элементам с текстовым контентом.