如何让XSLT以最少侵入性的方式表达属性?

时间:2012-09-19 22:26:50

标签: xslt xslt-1.0

我有这样的XSLT 1.0:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:template match="paragraph">
    <p>
      <xsl:apply-templates/>
    </p>
  </xsl:template>
</xsl:stylesheet>

只有,有很多很多模板与第一个相似。我希望在每个模板中都有一个特定的属性,但我想进行最小的修改以将其拉下来。这是我尝试的第一件事:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:template match="paragraph">
    <p>
      <xsl:apply-templates/>
    </p>
  </xsl:template>

  <xsl:template match="@class">
    <xsl:attribute name="class">
      <xsl:value-of select="@class"/>
    </xsl:attribute>
  </xsl:template>
</xsl:stylesheet>

但那没用。我试过这个:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:template match="paragraph">
    <p>
      <xsl:attribute name="class">
        <xsl:value-of select="@class"/>
      </xsl:attribute>
      <xsl:apply-templates/>
    </p>
  </xsl:template>
</xsl:stylesheet>

但要在每个模板中完成这项工作需要大量的代码重复。这是我能做的最好的,还是有更合适的方法来使这项工作?

2 个答案:

答案 0 :(得分:2)

在您的初步尝试中

  <xsl:template match="@class">
    <xsl:attribute name="class">
      <xsl:value-of select="@class"/>
    </xsl:attribute>
  </xsl:template>

此模板的上下文节点是class属性节点,因此value-of应选择.

  <xsl:template match="@class">
    <xsl:attribute name="class">
      <xsl:value-of select="."/>
    </xsl:attribute>
  </xsl:template>

但是,您还应注意,裸<xsl:apply-templates/>仅应用与当前节点的 children 匹配的模板,并且由于属性节点在XSLT数据模型中不计入子节点{{ 1}}模板不会触发。您可能需要修改@class模板以说明

paragraph

应用与 <xsl:template match="paragraph"> <p> <xsl:apply-templates select="@*|node()"/> </p> </xsl:template> 元素的属性及其子元素匹配的模板。

答案 1 :(得分:2)

如果您确实不想对现有模板规则进行任何更改,请添加优先级高于“p”等规则的模板规则,如下所示:

<xsl:template match="*[@class]" priority="100">
  <xsl:variable name="v">
    <xsl:next-match/>
  </xsl:variable>
  <xsl:apply-templates select="$v" mode="add-attribute">
    <xsl:with-param name="att" select="@class"/>
  </xsl:apply-templates>
</xsl:template>

<xsl:template match="*" mode="add-attribute">
  <xsl:param name="att" as="attribute()"/>
  <xsl:copy>
     <xsl:copy-of select="@*, $att"/>
     <xsl:apply-templates mode="#current"/>
  </xsl:copy>
</xsl:template>

在1.0中你必须将它放在一个单独的模块中并使用apply-imports而不是next-match。