XSLT如何检查当前节点是否具有任何属性

时间:2014-04-21 08:15:02

标签: xslt

我有动态的xml文件。有许多元素,有些可能有属性或可能没有。这是在xsd文件中定义的。

我正在使用递归方法(for-each)逐个显示节点内容。但是,如果任何标签具有任何属性,则条件不匹配,并且不显示该标签的内容。

我想检查当前元素是否具有任何属性。如果还有显示内容,否则也显示标签的内容。

我的xslt代码:

<xsl:template match="node()" mode="chapter">
    <xsl:for-each select="node()">
       <xsl:if test="current()[name() = 'CHAPTER']">
          <fo:block>
             <xsl:apply-templates select="current()[name() = 'CHAPTER']" mode="chapter" />
          </fo:block>
      </xsl:if>
   </xsl:for-each>
</xsl:template>

在上面的代码中,在一个xml输入中,CHAPTER标签有一个属性。因此if条件变为false并且它不会进入if块,尽管当前节点是CHAPTER。

我想检查CHAPTER是否有任何属性。 请建议。

提前谢谢。

2 个答案:

答案 0 :(得分:3)

您可以在条件中添加另一个谓词,例如:

<xsl:if test="name() = 'CHAPTER' and not(@*)">

这不会处理具有属性的CHAPTER个节点。

答案 1 :(得分:1)

你的代码看起来有点过于复杂了。您有一个匹配任何节点的模板,然后在每个子节点上循环,然后测试它是否为CHAPTER,然后您似乎在CHAPTER上应用其他模板。因此,您的模板并没有真正做任何特别有用的事情,并且很难遵循业务逻辑。

我认为你应该以模式身份转换风格的方式来编写它,你可以创建模板来处理你感兴趣的部分或扔掉你不感兴趣的部分。通过做这样的事情,您上面的模板可能看起来更像:

<xsl:template match="CHAPTER">
    <fo:block>
        <!-- anything else related specifically to CHAPTER element here -->

        <!-- process children of chapter using other templates... -->
        <xsl:apply-templates/>
    </fo:block>
</xsl:template>

如果您只想处理没有属性的CHAPTER元素,可以使用:

<xsl:template match="CHAPTER[not(@*)]">
    <fo:block>
        <!-- anything else related specifically to CHAPTER element here -->

        <!-- process children of chapter using other templates... -->
        <xsl:apply-templates/>
    </fo:block>
</xsl:template>

在上面的模板中,您将处理与CHAPTER直接相关的所有内容,然后您将定义子模板以处理您感兴趣的其他元素/节点。这会将您的代码分解为很简单的部分,例如:

<xsl:template match="CHAPTER[not(@*)]">
    <fo:block>
        <!-- anything else related specifically to CHAPTER element here -->

        <!-- process children of CHAPTER element using other templates... -->
        <xsl:apply-templates/>
    </fo:block>
</xsl:template>

<xsl:template match="TITLE">
   <fo:block font-size="18pt" font-family="sans-serif">
     <xsl:copy-of select="text()"/>
   </fo:block>
</xsl:template>

<xsl:template match="SYNOPSIS">
    <!-- we are not interested in the SYNOPSIS, so do nothing! -->
<xsl:template>

<!-- identity transform driver -->
<xsl:template match="node() | @*">
    <xsl:copy>
        <xsl:apply-templates select="node() | @*"/>
    </xsl:copy>
</xsl:template>

在上面我想象你的CHAPTER元素也可能有TITLE个子元素,并且你可能想要在另一个fo:block中输出它们。我还想象你的CHAPTER元素可能有一个SYNOPSIS子元素,你想忽略它并且不会产生任何输出。

您还可以通过Googling for XSLT身份转换找到这种XSLT编码风格的大量其他示例。