Reputation: 185
I have a solution from an earlier post that was kindly provided by Dimitre Novatchev.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:my="my:my">
<xsl:output method="xml" version="1.0" encoding="iso-8859-1" indent="yes"/>
<xsl:key name="kPhysByName" match="KB_XMod_Modules" use="Physician"/>
<xsl:template match="/">
<result>
<xsl:apply-templates/>
</result>
</xsl:template>
<xsl:template match="/*/*/*[starts-with(name(), 'InfBy')]">
<xsl:variable name="vCur" select="."/>
<xsl:for-each select="document('doc2.xml')">
<xsl:variable name="vMod" select="key('kPhysByName', $vCur)"/>
<xsl:copy>
<items>
<item>
<label>
<xsl:value-of select="$vMod/Physician"/>
</label>
<value>
<xsl:value-of select="$vMod/XModID"/>
</value>
</item>
</items>
</xsl:copy>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
I now need to use additional fields in my source XML and need the existing labels intact but I'm having problems getting this going.
<instance>
<NewTag>Hello</newTag1>
<AnotherNewTag>Everyone</AnotherNewTag>
<InfBy1>Dr Phibes</InfBy1>
<InfBy2>Dr X</InfBy2>
<InfBy3>Dr Chivago</InfBy3>
</instance>
It drops the additional labels and outputs
<result xmlns:my="my:my">
HelloEveryone
<items>
<item>
<label>Dr Phibes</label>
<value>60</value>
</item>
</items>
...
I've been experimenting a lot with
<xsl:otherwise>
<xsl:copy-of select=".">
</xsl:copy-of>
</xsl:otherwise>
but being an xsl newbie I can't seem to get this to work. I've a feeling I'm barking up the wrong tree!
Does anyone have any ideas?
Thanks,
Will
Upvotes: 0
Views: 338
Reputation: 338108
This is a side-effect of <xsl:apply-templates>
which tries to find a matching template for every child node it encounters, in conjunction with implied XSLT "default behavior".
In your case, it encounters <NewTag>
and <AnotherNewTag>
, but there are no templates for these nodes.
The default behavior (the hidden default template) that catches this case copies the text value of the element to the output stream.
The text value of <NewTag>
is "Hello", that of <AnotherNewTag>
is "Everyone", so you see "HelloEveryone".
If you do not want this, write your own template that catches these nodes:
<xsl:template match="NewTag|AnotherNewTag">
<xsl:copy-of select="." />
</xsl:template>
Alternatively, write one that catches any unhandled element node:
<!-- empty templates do nothing (matched nodes do not appear in the output) -->
<xsl:template match="*" />
If you want to copy unhandled nodes unchanged but still want to recursively apply templates within them, the identity template (@Alejandro's answer shows it) is the way to go.
Upvotes: 0
Reputation:
Your NewTag
and AnotherNewTag
elements are matched by the Built-in Template Rules. If you want another kind of transformation you need to declare such rules.
need the existing labels intact
Then you are looking for the identity rule
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
Upvotes: 2