【问题标题】:xslt test on a parameter of a tagxslt 测试标签的参数
【发布时间】:2011-05-27 08:14:58
【问题描述】:

我想在 xslt 中创建一个模板,其中包含我要匹配的标记的参数的条件。

例如: 如果我有标签<par class="class1"><par class="class2">

我想创建一个这样的模板:

<xsl:template match="par">
 <xsl:if test="class=class1">
  <fo:block
    space-before="3pt"
    space-after="3pt">

    <xsl:apply-templates />

  </fo:block>
 </xsl:if>
 <xsl:otherwise>
  <fo:block
    space-before="10pt"
    space-after="10pt">

    <xsl:apply-templates />

  </fo:block>
 </xsl:otherwise>
</xsl:template>

但它不起作用。如何测试标签的参数?

提前致谢。

【问题讨论】:

  • 如果您学习行话,您会发现更容易获得答案(无论是从这里还是从书籍和在线搜索中)。您说的是元素和属性,而不是标签和参数。

标签: xml xslt xsl-fo


【解决方案1】:

起初&lt;xsl:if/&gt; 是“独立”指令。如果您需要默认情况,您可以使用xsl:choose

在您的代码中xsl:if 测试 xpath 无效。使用@attribute_name 进行属性访问,使用单引号作为字符串文字。

固定代码:

<xsl:template match="par">
 <xsl:choose>
 <xsl:when test="@class = 'class1'">
  <fo:block
    space-before="3pt"
    space-after="3pt">
    <xsl:apply-templates />
  </fo:block>
 </xsl:when>
 <xsl:otherwise>
  <fo:block
    space-before="10pt"
    space-after="10pt">
    <xsl:apply-templates />
  </fo:block>
 </xsl:otherwise>
 <xsl:choose>
</xsl:template>

但是有更优雅的解决方案适合您的任务:

<xsl:template match="par">
    <fo:block
      space-before="10pt"
      space-after="10pt">

        <xsl:if test="@class = 'class1'">
            <xsl:attribute name="space-before" select="'3pt'"/>
            <xsl:attribute name="space-after" select="'3pt'"/>
        </xsl:if>

        <xsl:apply-templates />

    </fo:block>
</xsl:template>

【讨论】:

    【解决方案2】:

    您实际上可以使用不同的模板,而不是使用&lt;xsl:if&gt;。像这样:

    <xsl:template match="par[@class='class1']">
      ..
    </xsl:template>
    
    <xsl:template match="par">
      ..
    </xsl:template>
    

    第二个模板用于任何与第一个不匹配的par 元素。虽然第二个模板可以匹配所有par 元素,但它被第一个覆盖,因为后者更具体。

    【讨论】:

      【解决方案3】:

      这些“参数”的技术术语是“属性”(以防万一有助于将来的搜索),您可以使用 @class 等来引用它们。

      还要注意&lt;xsl:otherwise&gt;不是&lt;xsl:if&gt;,而是&lt;xsl:choose&gt;

      <xsl:template match="par">
        <xsl:choose>
          <xsl:when test="@class='class1'">
            <fo:block
              space-before="3pt"
              space-after="3pt">
      
              <xsl:apply-templates />
      
            </fo:block>
          </xsl:when>
          <xsl:otherwise>
            <fo:block
              space-before="10pt"
              space-after="10pt">
      
              <xsl:apply-templates />
      
            </fo:block>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:template>
      

      或者,为了更好地展示实际差异,

      <xsl:template match="par">
        <fo:block>
          <xsl:choose>
            <xsl:when test="@class='class1'">
              <xsl:attribute name='space-before'>3pt</xsl:attribute>
              <xsl:attribute name='space-after'>3pt</xsl:attribute>
            </xsl:when>
            <xsl:otherwise>
              <xsl:attribute name='space-before'>10pt</xsl:attribute>
              <xsl:attribute name='space-after'>10pt</xsl:attribute>
            </xsl:otherwise>
          </xsl:choose>
          <xsl:apply-templates/>
        </fo:block>
      </xsl:template>
      

      【讨论】:

      • 你对属性引号有误:&lt;xsl:attribute name="space-after" select="'10pt'"/&gt;`
      • 其实你们都错了;您使用哪些引号将属性值括起来,以及其中的字符串值实际上是可以互换的,只要您不使用相同的引号即可。答案的真正问题是test 子句没有将class1 值括在引号中。顺便说一句,您不能在 xslt1 中在 &lt;xsl:attribute&gt; 上使用 select,只有 XSLT2 可以这样做。
      【解决方案4】:

      您使用@访问属性,您可以按如下方式测试属性的值:

      <xsl:if test="@class = 'class1'">
          ....
      </xsl:if>
      

      或使用

      检查属性是否存在
      <xsl:if test="@class">
         ...
      </xsl:if>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-12-15
        • 1970-01-01
        • 1970-01-01
        • 2021-02-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多