How to preserve all tags, structure and text in an XML document, replacing only some with XSLT?

I am 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 just simply ignores all other tags and removes them as well as their content from the output, and I'm left with just the headers converted to h1s. What I would like to do is keep my document structure by replacing only some of its tags.

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

      

Not sure where in the XSLT manual to start looking.

+3


source to share


2 answers


As O. Carper says, the solution to this is to add an identity pattern to your transformation and simply override the parts you need. This would be a 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 input to a sample, this gives:



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

      

If you really want to keep the original XML, but replace <title>

, you can simply remove the middle <xsl:template>

and you should get the result:

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

      

+7


source


You only want to replace the elements <title>

. However, in your XSLT, you define a template for the root element ( /

) of your document and replace the entire root element with the content of your template.

What you actually want to do is define an id transformation template (google this, this is an important concept in XSLT) to copy basically everything from the original document and the template that matches your elements <title>

and replace them with your new code, e.g .:



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

      

+2


source







All Articles