使用xsl方法的问题

时间:2009-11-30 17:11:16

标签: xml xslt

使用XSL我试图改变这个XML:

<book><title>This is a <b>great</b> book</title></book>

进入这个XML:

<book>This is a <bold>great</bold> book</book>

使用此xsl:

<xsl:for-each select="book/title/*">
<xsl:choose>
    <xsl:when test="name() = 'b'">
        <bold>
            <xsl:value-of select="text()"/>
        </bold>
    </xsl:when>
    <xsl:otherwise>
        <xsl:value-of select="text()"/>
    </xsl:otherwise>
</xsl:choose>
</xsl:for-each>

但我的输出看起来像这样:

<book><bold>great</bold></bold>

任何人都可以解释为什么<title>的根文本会丢失吗?我相信我的for-each select语句可能需要修改,但我无法弄清楚应该是什么。

请注意,由于样式表的复杂性,我无法使用<xsl:template match>

谢谢!

2 个答案:

答案 0 :(得分:7)

这个XPath表达式:

book/title/*

表示“book/title”的所有子元素。在您的情况下,book/title有3个子节点

  • 文字节点:This is a
  • 元素节点:<b>...</b>
  • 文字节点:book

如您所见,其中只有一个是元素,并被选中。如果要获取所有子节点(文本和元素),请使用:

book/title/node()

如果您想单独获取文本节点,请使用:

book/title/text()

答案 1 :(得分:1)

虽然Pavel Minaev提供了这个问题的答案,但必须注意的是,这个问题表明了一个非常糟糕的方法(可能是由于缺乏经验)对XSLT进行处理

这项任务可以以优雅的方式完成,展示了XSLT的强大功能:

在提供的XML文档上应用上述转换时:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes"/>
    <xsl:template match="node()|@*">
      <xsl:copy>
         <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
    </xsl:template>

    <xsl:template match="title">
      <xsl:apply-templates/>
    </xsl:template>

    <xsl:template match="title/b">
      <bold>
       <xsl:apply-templates/>
      </bold>
    </xsl:template>
</xsl:stylesheet>

产生了想要的结果:

<book><title>This is a <b>great</b> book</title></book>

这是一个基本的XSLT设计模式的一个很好的例证 - 覆盖了elment重命名/展平的身份规则