How do I preserve all tags, structure and text in an xml document replacing only some with XSLT?

一曲冷凌霜 提交于 2020-01-04 03:15:41

问题


I've been trying to apply a simple xsl style to an xml document:

<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>

Unfortunately, this seems to just simply ignore all other tags and remove them as well as their contents from the output, and I'm only left with titles converted to h1s. What I would like to be able to do is to have my document's structure remain, while replacing only some of its tags.

So that for example if I have this document:

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

I could get this:

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

No quite sure where in the XSLT manual to start looking.


回答1:


As O. R. Mapper says, the solution to this is to add an identity template to your transform and just override the parts you need to. This would be the complete solution:

<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>

When run on your sample input, this produces:

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

If you really just want to preserve your original XML but replace the <title>, you can just remove the middle <xsl:template> and you should get the result:

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



回答2:


You want to replace just <title> elements. However, in your XSLT, you define a template for the root element (/) of your document, and you replace the entire root element with the contents of your template.

What you actually want to do is define an identity transform template (google this, it's an important concept in XSLT) to copy basically everything from your source document, and a template that only matches your <title> elements and replaces them with your new code, like this:

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


来源:https://stackoverflow.com/questions/14662409/how-do-i-preserve-all-tags-structure-and-text-in-an-xml-document-replacing-only

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!