Reputation: 2083
Given an xml file that has elements a, b, c and d is it possible to write an XSLT that will alter only element "c" and blindly pass all other elements?
For example:
<?xml version="1.0" encoding="UTF-8"?>
<Person>
<a>pass me blindly</a>
<b>pass me blindly</b>
<c>I need XSLT to convert me</c>
<d>pass me blindly</d>
</Person>
Is it possible to have an XSLT that does the transform of "c" and yet all of the other elements are passed as they are in the source?
I would end up with:
<?xml version="1.0" encoding="UTF-8"?>
<Person>
<a>pass me blindly</a>
<b>pass me blindly</b>
<c>I've been CONVERTED!</c>
<d>pass me blindly</d>
</Person>
And yes my knowledge level of XSLT is limited.
Upvotes: 2
Views: 200
Reputation: 167716
As you mention Altova you might also be able to use XSLT 3 (if you have a current version of Altova) and in XSLT 3 you can use xsl:mode on-no-match
with the different values on-no-match? = "deep-copy" | "shallow-copy" | "deep-skip" | "shallow-skip" | "text-only-copy" | "fail"
, see https://www.w3.org/TR/xslt-30/#built-in-rule and https://www.w3.org/TR/xslt-30/#declaring-modes, a declaration of
<xsl:mode on-no-match="shallow-copy"/>
would establish the identity transformation as the built-in rules for the unnamed mode. Then you would only need to add a template for that element you want to transform.
Upvotes: 0
Reputation: 172
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<?xml-stylesheet type="text/xml" href=".\XSLTFile1.xslt"?>
<Person >
<a>pass me blindly</a>
<b>pass me blindly</b>
<c>I need XSLT to convert me</c>
<d>pass me blindly</d>
</Person>
The following XSL Transformation template will give you the desired result
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" omit-xml-declaration="yes" />
<xsl:template match="xsl:stylesheet" />
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="c">
<c>I've been CONVERTED!</c>
</xsl:template>
</xsl:stylesheet>
Upvotes: 3
Reputation: 29052
You have two possibilities to achieve what you want:
The first one copies all nodes except for the white-listed which are processed differently:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" omit-xml-declaration="yes" />
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*" />
</xsl:copy>
</xsl:template>
<xsl:template match="c">
<xsl:value-of select="concat('The node ',name(),' is being processed.')" />
</xsl:template>
</xsl:stylesheet>
The second one copies only the blacklisted nodes which should not processed further:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" omit-xml-declaration="yes" />
<xsl:template match="node() | @*" priority="-1">
<xsl:copy>
<xsl:apply-templates select="node() | @*" />
</xsl:copy>
</xsl:template>
<xsl:template match="a | b | d" priority="1">
<xsl:copy>
<xsl:apply-templates select="node() | @*" />
</xsl:copy>
</xsl:template>
<xsl:template match="*[parent::Person]" priority="0">
<xsl:value-of select="concat('The node ',name(),' is being processed.')" />
</xsl:template>
</xsl:stylesheet>
Upvotes: 1