XSL if else condition

匿名 (未验证) 提交于 2019-12-03 03:04:01

问题:

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.

Eg: 1 of the node has 0 File(s) found and the other has attribs such as <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='&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> 

How would i identify if a node has just strings or attribs and based on that I can get the values either String or attrib values respectively.

回答1:

You can replace your whole xsl:choose instruction with:

<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> 


回答2:

We can achieve if else by using below code

<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



回答3:

I. Xpath 1.0 solution - use this single XPath expression:

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

Here is a XSLT-based verification:

<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> 

when this transformation is applied on the provided XML document (slightly corrected to be made well-formed):

<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> 

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 

Explanation We use these facts:

  1. For any string $s, substring($s, Infinity) is the empty string.

  2. 1 div 0 is Infinity

  3. By definition number(true()) is 1 and number(false()) is 0.

    II. XPath 2.0 solution:

This is much easier in XPath 2.0 because the language has standard if/then/else operator.

Use:

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

XSLT 2.0 verification:

<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> 

when this transformation is applied on the same XML document (above), again 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 


回答4:

XPath //*[not(@*)] will select all elements, which don't have attributes.



回答5:

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 if else condition
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!