Reputation: 9945
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.
Upvotes: 3
Views: 642
Reputation: 101730
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>
Upvotes: 7
Reputation: 20760
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>
Upvotes: 2