【问题标题】:How do I preserve all tags, structure and text in an xml document replacing only some with XSLT?如何保留 xml 文档中的所有标签、结构和文本,只用 XSLT 替换一些?
【发布时间】:2013-01-17 17:11:34
【问题描述】:

我一直在尝试将简单的 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 手册的哪个位置开始查找。

【问题讨论】:

    标签: xml xslt xml-parsing


    【解决方案1】:

    正如 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 但替换 &lt;title&gt;,则只需删除中间的 &lt;xsl:template&gt;,您应该会得到结果:

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

    【讨论】:

      【解决方案2】:

      您只想替换 &lt;title&gt; 元素。但是,在您的 XSLT 中,您为文档的根元素 (/) 定义了一个模板,然后将整个根元素替换为模板的内容。

      您实际上想要做的是定义一个身份转换模板(谷歌这个,这是 XSLT 中的一个重要概念),基本上从源文档中复制所有内容,以及一个模板,只 匹配您的 &lt;title&gt; 元素并用您的新代码替换它们,如下所示:

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

      【讨论】:

      • 我会在&lt;xsl:template match="//title"&gt; 模式中删除前导//,这在模式中不是必需的。写&lt;xsl:template match="title"&gt; 就可以了。
      • 最好使用&lt;xsl:apply-templates select="@* | node()" /&gt; 而不是&lt;xsl:value-of select="." /&gt;,因为可能存在子节点或属性。 +1 有正确的想法。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-23
      • 1970-01-01
      • 1970-01-01
      • 2012-10-08
      • 1970-01-01
      • 2014-05-01
      相关资源
      最近更新 更多