2010-07-02 70 views
6
<xsl:choose> 
    <xsl:when test="long convoluted expression"> 
     <xsl:element name="Class">123</xsl:element> 
     <a lot more xsl:elements> 
    </xsl:when> 
    <xsl:when test="next very long expression"> 
     <xml:element name="Class">124</xsl:element> 
     <a lot more xsl:elements> 
    </xsl:when> 
    <tens of more similar xsl:when> 
</xsl:choose> 

有没有一种方法来简化上面的代码与条件?对于给定对象的每个类值,都会有数十行附加属性。这些属性根据类的值形成集合。 0-99级有一组额外标签,每秒100-199级,当这些额外标签集中的一个发生变化时形成维护噩梦。XSLT条件/变量范围

我正在考虑这样一个解决方案:

<xsl:choose> 
    <xsl:when test="long convoluted expression"> 
     <xml:element name="Class">123</xsl:element> 
     <xsl:variable name="outputclass" select="123"> 
    </xml:when> 
    <xsl:when test="next very long expression"> 
     <xml:element name="Class">124</xsl:element> 
     <xsl:variable name="outputclass" select="124"> 
    </xsl:when> 
</xsl:choose> 
<xsl:choose> 
    <xsl:when test="$outputclass > 99"> 
     <xml:elements for classes 100-199 here> 
    </xsl:when> 
<xsl:choose> 

但当然这失败,因为OutputClass类变量不是在同一范围内。任何方式来解决这个问题?

+0

这很混乱。如果您添加示例输入和输出文档,它可能会变得更清晰。 – 2010-07-02 12:31:33

+0

好问题(+1)。在我的答案中看到* real * best解决方案 - 完整的代码和解释。 :) – 2010-07-02 13:28:34

回答

6

解决这个问题的最佳解决方案是知名

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="/"> 
    <xsl:variable name="voutType"> 
     <xsl:choose> 
     <xsl:when test="long convoluted expression">123</xsl:when> 
     <xsl:when test="next very long expression">124</xsl:when> 
     <!-- Etcetera ... --> 
     </xsl:choose> 
    </xsl:variable> 

    <Class><xsl:value-of select="$voutType"</Class> 
     <xsl:choose> 
      <xsl:when test="not($voutType > 99)"> 
       <!-- elements for classes 0 - 99 here --> 
      </xsl:when> 
      <xsl:otherwise> 
       <!-- elements for classes 100-199 here --> 
      </xsl:otherwise> 
     <xsl:choose> 
</xsl:template> 
</xsl:stylesheet> 

请注意

  1. 为了给值的变量($voutType),<xsl:choose>指令必须是里面的机体的<xsl:variable>

  2. 您只需指定<Class>元素一次 - 在其他任何位置之外。

  3. 如果元件名称已知,则不必使用<xsl:element>

+0

这是一个美丽的解决方案。与其他解决方案一样易于维护,但更短。你可以在一个我不知道的变量中嵌套选择。谢谢! – diskis 2010-07-02 13:52:20

+0

@diskis:我很高兴你不接受我的回答。这似乎不够,但我认为这可能会让你朝着正确的方向前进。这绝对是更好的方式。 – MJB 2010-07-02 14:09:02

+0

什么使得任何解决方案“众所周知”? – n611x007 2015-05-08 11:00:39

0

我只做过几次XSLT,但每次看起来像是一个巨大的维护噩梦。无论如何,我认为你可以设置一个变量来说明这个类是什么,然后调用一个函数作为xsl:template作为arg与类匹配。您会将该函数声明为xsl:template name,因为您不想自动匹配它。在函数内部,你应该能够编写这100个值。不确定这是否有帮助,但它可能以某种方式组织代码。

+0

是的,谢谢。快速测试表明,这将完全符合我的目的。现在只需要学习xml:with-param语法,而且我会少花一些模板。 – diskis 2010-07-02 13:11:26

1

如果你想可以很容易地指定了一堆属性(!标签又名元素),那么它听起来好像属性集是你需要什么,你可能不需要变量:

http://www.w3.org/TR/xslt#attribute-sets

这假定属性值本身不依赖于类的值;只有他们的存在。

如果元素真的是你的意思,请尝试使用具有输入参数的命名模板。在你的样式表的顶层:

<xsl:template name="classdef"> 
    <xsl:param name="classid"/> 
    <!-- Note: I put the class elem in here so I don't have to 
     write individual class ids more than once --> 
    <xsl:element name="Class"><xsl:value-of select="$classid"/></xsl:element> 
    <xsl:choose> 
    <xsl:when test="$classid > 99"> 
     ... 
    </xsl:when> 
    </xsl:choose> 
</xsl:template> 

,并在其他的模板:

<xsl:call-template name="classdef"> 
    <xsl:with-param name="classid">124</xsl:with-param> 
</xsl:call-template> 

对PARAMS更多信息请参见http://www.w3.org/TR/xslt#variables

+0

谢谢,这与MJB发布的解决方案基本相同,并且可以完美满足我的需求。 我会回来给你一个upvote当我得到足够的声誉做到这一点:) – diskis 2010-07-02 13:16:17