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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 14:55:16  来源:igfitidea点击:

XSL if else condition

xmlxsltxpath

提问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='&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 Stringor attrib valuesrespectively.

我将如何确定,如果一个节点只是字符串或attribs和基于我可以得到的值或者Stringattrib 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

我的输出

enter image description here

在此处输入图片说明

回答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('&#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):

当此转换应用于提供的 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>

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:

解释我们使用这些事实:

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

  2. 1 div 0is Infinity

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

    II. XPath 2.0 solution:

  1. 对于任何字符串$ssubstring($s, Infinity)是空字符串。

  2. 1 div 0Infinity

  3. 根据定义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('&#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:

当此转换应用于同一个 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()]"具有文本内容的元素。