使用 xsl:choose 和 xsl:when 时避免代码重复 [英] Avoid code repetition when using xsl:choose and xsl:when

查看:26
本文介绍了使用 xsl:choose 和 xsl:when 时避免代码重复的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否有一种巧妙的方法来简化以下样式表,以避免在每个块之间只有一个变量发生变化时重复整个 when 块?

Is there a clever way to simplify the following stylesheet in order to avoid repeating a whole when block when only one variable is changing between each of those?

理想情况下,我想要这样的东西,在 $i 上循环 6 次:

Ideally I would like something like this, looping 6 times on $i:

<xsl:when test="$depth &gt; $i">
    [...]
    <xsl:value-of select="substring($npath,($nlength - $i*2),1) - 1"/>
    [...]
</xsl:when>

我使用的是 XSLT 1.0.

I'm using XSLT 1.0.

XML 输入

<?xml version='1.0'?>
<?xml-stylesheet type="text/xsl" href="stylesheet.xsl" version="1.0"?>
<root>
  <item>Main_A
    <item>Item_A</item>
    <item>Item_B
      <item>Subitem_A</item>
      <item>Subitem_B</item>
    </item>
    <item>Item_C</item>
  </item>
  <item>Main_B
    <item>Item_A
      <item>Subitem_A</item>
      </item>
    <item>Item_B</item>
  </item>
</root>

XSLT 1.0 样式表

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="root">
  <html>
    <body>
      <xsl:apply-templates select="item">
        <xsl:with-param name="depth" select="1"/>
      </xsl:apply-templates>
    </body>
  </html>
</xsl:template>

<xsl:template match="item">
  <xsl:param name="depth" select="1"/>
  <xsl:if test="$depth &lt; 10">
    <ul>
      <li>
        <xsl:text>path</xsl:text>
        <xsl:call-template name="loopnumformat">
          <xsl:with-param name="depth" select="$depth"/>
        </xsl:call-template>
        <xsl:text> = </xsl:text>
        <xsl:apply-templates match="item">
          <xsl:with-param name="depth" select="$depth + 1"/>
        </xsl:apply-templates>
      </li>
    </ul>
  </xsl:if>
</xsl:template>

<xsl:template name="loopnumformat">
  <xsl:param name="depth" select="1"/>
  <xsl:variable name="npath">
    <xsl:number level="multiple" from="*[10]"/>
  </xsl:variable>
  <xsl:variable name="nlength">
    <xsl:value-of select="string-length($npath)"/>
  </xsl:variable>

  <xsl:choose>
    <xsl:when test="$depth &gt; 2">
      <xsl:text>:</xsl:text>
      <xsl:value-of select="substring($npath,($nlength - 2*2),1) - 1"/>
      <xsl:call-template name="loopnumformat">
        <xsl:with-param name="depth" select="$depth - 1"/>
      </xsl:call-template>
    </xsl:when>
    <xsl:when test="$depth &gt; 1">
      <xsl:text>:</xsl:text>
      <xsl:value-of select="substring($npath,($nlength - 1*2),1) - 1"/>
      <xsl:call-template name="loopnumformat">
        <xsl:with-param name="depth" select="$depth - 1"/>
      </xsl:call-template>
    </xsl:when>
    <xsl:when test="$depth &gt; 0">
      <xsl:text>:</xsl:text>
      <xsl:value-of select="substring($npath,($nlength - 0*2),1) - 1"/>
      <xsl:call-template name="loopnumformat">
        <xsl:with-param name="depth" select="$depth - 1"/>
      </xsl:call-template>
    </xsl:when>
  </xsl:choose>

</xsl:template>

</xsl:stylesheet>

HTML 输出

<html>
<body>
  <ul>
    <li>path:0 = Main_A
      <ul>
        <li>path:0:0 = Item_A</li>
      </ul>
      <ul>
        <li>path:0:1 = Item_B
          <ul>
            <li>path:0:1:0 = Subitem_A</li>
          </ul>
          <ul>
            <li>path:0:1:1 = Subitem_B</li>
          </ul>
        </li>
      </ul>
      <ul>
        <li>path:0:2 = Item_C</li>
      </ul>
    </li>
  </ul>
  <ul>
    <li>path:1 = Main_B
      <ul>
        <li>path:1:0 = Item_A
          <ul>
            <li>path:1:0:0 = Subitem_A</li>
          </ul>
        </li>
      </ul>
      <ul>
        <li>path:1:1 = Item_B</li>
      </ul>
    </li>
  </ul>
</body>
</html>

推荐答案

是否有一种巧妙的方法来简化以下样式表,以避免在每个样式表之间只有一个变量发生变化时重复整个 when 块?

Is there a clever way to simplify the following stylesheet in order to avoid repeating a whole when block when only one variable is changing between each of those?

这取决于具体情况,但在您的特定情况下,您可以这样做的一种方法是将 xsl:choose 移到里面,以便在每种情况下都相同的部分是每个只表达一次:

It depends on the circumstances, but in your particular case, one way you could do it would be to move the xsl:choose inside, so that the parts that are the same in every case are expressed only once each:

  <xsl:text>:</xsl:text>
  <xsl:choose>
    <xsl:when test="$depth &gt; 2">
      <xsl:value-of select="substring($npath,($nlength - 2*2),1) - 1"/>
    </xsl:when>
    <xsl:when test="$depth &gt; 1">
      <xsl:value-of select="substring($npath,($nlength - 1*2),1) - 1"/>
    </xsl:when>
    <xsl:when test="$depth &gt; 0">
      <xsl:value-of select="substring($npath,($nlength - 0*2),1) - 1"/>
    </xsl:when>
  </xsl:choose>
  <xsl:call-template name="loopnumformat">
    <xsl:with-param name="depth" select="$depth - 1"/>
  </xsl:call-template>

但是当 xsl:number 不能完全满足您的需求时,您似乎会竭尽全力使用它.看起来你可以更简单地完成整个事情:

But you seem to be going to extreme lengths to use xsl:number when it doesn't quite meet your needs. It appears that you can do the whole thing much more simply:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template match="root">
    <html>
      <body>
        <xsl:apply-templates select="item" />
      </body>
    </html>
  </xsl:template>

  <xsl:template match="item">
    <xsl:param name="path-prefix" select="'path'"/>
    <!-- if there are fewer than nine ':' characters in the path prefix for
         this item ... -->
    <xsl:if test="string-length($path-prefix) - string-length(translate($path-prefix, ':', '')) &lt; 9">
      <xsl:variable name="my-path"
          select="concat($path-prefix, ':', position() - 1)" />
      <ul>
        <li>
          <xsl:value-of select="$my-path"/>
          <xsl:text> = </xsl:text>
          <xsl:apply-templates select="text()[1]"/>
          <xsl:apply-templates select="item">
            <xsl:with-param name="path-prefix" select="$my-path"/>
          </xsl:apply-templates>
        </li>
      </ul>
    </xsl:if>
  </xsl:template>

</xsl:stylesheet>

也许您甚至可以去掉 xsl:if,这似乎是为了满足原始样式表中 loopnumformat 模板的限制-- 此版本没有固有的深度限制.请注意,它确实假设您要复制到输出文档中的文本节点将仅限于每个 中的第一个节点,但是修改样式表以代替复制也很容易所有这些.

Perhaps you could even get rid of the xsl:if, which seems as if it may have been present to serve the limitations of the loopnumformat template in your original stylesheet -- this version has no inherent depth limitation. Note that it does assume that the text nodes you want to copy into the output document will be limited to the first in each <item>, but it would be easy enough to modify the stylesheet to instead copy all of them.

这篇关于使用 xsl:choose 和 xsl:when 时避免代码重复的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆