xml XSL if else 条件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7239308/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
XSL if else condition
提问by AabinGunz
I have a requirement where I'd like to have if else statement to check whether a node has attributes or it has just string.
我有一个要求,我希望使用 if else 语句来检查节点是否具有属性或只有字符串。
Eg: 1 of the node has 0 File(s) foundand the other has attribs such as <autoincludesystem_info mdate='08/23/2011' mtime='09:51' ampm='PM' filesize='64' filename='AFP_p.tgp' />
例如:节点中的 1 个具有0 File(s) found,另一个具有属性,例如<autoincludesystem_info mdate='08/23/2011' mtime='09:51' ampm='PM' filesize='64' filename='AFP_p.tgp' />
Below is a sample of two nodes
下面是两个节点的示例
<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>
How would i identify if a node has just strings or attribs and based on that I can get the values either Stringor attrib valuesrespectively.
我将如何确定,如果一个节点只是字符串或attribs和基于我可以得到的值或者String或attrib values分别。
采纳答案by Emiliano Poggi
You can replace your whole xsl:chooseinstruction with:
您可以将整个xsl:choose指令替换为:
<xsl:apply-templates select="autoIncludeSystem"/>
and then add two templates:
然后添加两个模板:
<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>
回答by AabinGunz
We can achieve if else by using below code
我们可以通过使用下面的代码来实现 if else
<xsl:choose>
<xsl:when test="something to test">
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
So here is what I did
所以这就是我所做的
<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>
My Output
我的输出


回答by Dimitre Novatchev
I. Xpath 1.0 solution - use this single XPath expression:
I. Xpath 1.0 解决方案 - 使用这个单一的 XPath 表达式:
concat(substring('String', 1 div boolean(text())),
' ',
substring('attrib values', 1 div boolean(@*))
)
Here is a XSLT-based verification:
这是一个基于 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>
when this transformation is applied on the provided XML document(slightly corrected to be made well-formed):
当此转换应用于提供的 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>
the wanted, correct result is produced:
产生了想要的、正确的结果:
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
ExplanationWe use these facts:
解释我们使用这些事实:
For any string
$s,substring($s, Infinity)is the empty string.1 div 0isInfinityBy definition
number(true())is1andnumber(false())is 0.II. XPath 2.0 solution:
对于任何字符串
$s,substring($s, Infinity)是空字符串。1 div 0是Infinity根据定义
number(true())是1并且number(false())是 0。二、XPath 2.0 解决方案:
This is much easier in XPath 2.0 because the language has standard if/then/elseoperator.
这在 XPath 2.0 中要容易得多,因为该语言具有标准if/then/else运算符。
Use:
使用:
if(text())
then 'String'
else if(@*)
then 'attrib values'
else ()
XSLT 2.0 verification:
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>
when this transformation is applied on the same XML document (above), again the wanted, correct result is produced:
当此转换应用于同一个 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
回答by Kirill Polishchuk
XPath //*[not(@*)]will select all elements, which don't have attributes.
XPath//*[not(@*)]将选择所有没有属性的元素。
回答by Michael Kay
You can do this easily enough using xsl:choose- but very often in XSLT, the better way to do conditional processing is to write different template rules to handle the different conditions. So write one template rule with match="*[@*]"to match elements that have attributes, and another with match="*[text()]"to match elements that have textual content.
您可以很容易地使用xsl:choose- 但通常在 XSLT 中,进行条件处理的更好方法是编写不同的模板规则来处理不同的条件。因此,编写一个模板规则match="*[@*]"以匹配具有属性的元素,并编写另一个模板规则以匹配match="*[text()]"具有文本内容的元素。

