如何在xml文档中保留所有标记,结构和文本,仅替换某些XSLT?

时间:2013-02-02 13:34:13

标签: xml xslt xml-parsing

我一直在尝试将简单的xsl样式应用于xml文档:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template match="/">
    <html>
      <body>

        <xsl:for-each select="//title">
          <h1><xsl:value-of select="."/></h1>
        </xsl:for-each>

      </body>
    </html>
  </xsl:template>

</xsl:stylesheet>

不幸的是,这似乎只是简单地忽略所有其他标签并从输出中删除它们以及它们的内容,而我只留下转换为h1s的标题。我希望能够做的是保留我的文档结构,同时只替换它的一些标签。

例如,如果我有这个文件:

<section>
  <title>Hello world</title>
  <p>Hello!</p>
</section>

我能得到这个:

<section>
  <h1>Hello world</h1>
  <p>Hello!</p>
</section>

不确定在XSLT手册中的哪个位置开始查找。

2 个答案:

答案 0 :(得分:7)

正如O. R. Mapper所说,解决方法是在变换中添加一个标识模板,然后覆盖你需要的部分。这将是完整的解决方案:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" indent="yes" omit-xml-declaration="yes"/>

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

  <xsl:template match="/">
    <html>
      <body>
        <xsl:apply-templates select="@* | node()" />
      </body>
    </html>
  </xsl:template>

  <xsl:template match="title">
    <h1>
      <xsl:apply-templates select="@* |node()" />
    </h1>
  </xsl:template>
</xsl:stylesheet>

在样本输入上运行时,会产生:

<html>
  <body>
    <section>
      <h1>Hello world</h1>
      <p>Hello!</p>
    </section>
  </body>
</html>

如果您真的只想保留原始XML但替换<title>,则可以删除中间<xsl:template>并获得结果:

<section>
  <h1>Hello world</h1>
  <p>Hello!</p>
</section>

答案 1 :(得分:2)

您想要只替换<title>元素。但是,在您的XSLT中,您为文档的根元素(/)定义了一个模板,并且用模板的内容替换整个根元素。

实际想要做的是定义一个身份转换模板(google this,这是XSLT中的一个重要概念)来复制源文档中的所有内容,以及仅的模板与您的<title>元素匹配,并将其替换为新代码,如下所示:

<xsl:template match="title">
    <h1><xsl:value-of select="."/></h1>
</xsl:template>