Reputation: 181
I Am trying to write XSLT code to add prefix namespaces to all nodes except few.
Sample XML:
<BatchPrepareDeliverArchive xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="schema">
<BatchInformation>
<RqUId>424000000071256187550913330</RqUId>
<BatchFeedId>CMLTREXT4240</BatchFeedId>
<BatchCount>7</BatchCount>
</BatchInformation>
<BatchDeliverArchive>
<Transactions>
<Transaction>
<TransactionUUID>90022016-01-140000001</TransactionUUID>
<CustomerData>
<GBD_Transactions>
<GBD_Transaction>
<Common_Data>
<Transaction_ID>90022016-01-140000001</Transaction_ID>
</Common_Data>
<Templates>
<Template>
<Template_Name>A21_LETTER_FINAL_NOTICE_OF_CANCELLATION_TPA</Template_Name>
<Transaction_ID>90022016-01-140000001</Transaction_ID>
</Template>
</Templates>
</GBD_Transaction>
</GBD_Transactions>
</CustomerData>
<DocInfo>
<Name>OPERATION NAME</Name>
</DocInfo>
</Transaction>
</Transactions>
</BatchDeliverArchive>
</BatchPrepareDeliverArchive>
I want to add urn prefix to all nodes except GBD_Transactions & its child elements.
I came up with this XSLT:
<xsl:stylesheet version="1.0" xmlns:urn="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="*">
<xsl:element name="urn:{local-name()}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="@*">
<xsl:element name="urn:{local-name()}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
All nodes are getting transformed here, which is not the expected output. Would appreciate any help on this!
Upvotes: 2
Views: 514
Reputation: 70648
If you want to ignore GBD_Transactions
elements, and its descendants, just add a template to match the relevant nodes, and use the identity template to copy them as-is.
Try adding this template to the XSLT
<xsl:template match="GBD_Transactions|GBD_Transactions//*|GBD_Transactions//@*">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
Note that matching on a specific element name has a higher priority than matching on *
, so this template should always be used ahead of the more generic one.
By the way, there is an issue with your template that matches "*". You probably change it to this...
<xsl:template match="*">
<xsl:element name="urn:{local-name()}">
<xsl:apply-templates select="@*|node()" />
</xsl:element>
</xsl:template>
This is because <xsl:apply-templates />
is the same as doing <xsl:apply-templates select="node()" />
and so will not select attributes. Thus, your existing template that matches @*
would not get called otherwise.
EDIT: If you want to stop the xsi:schemaLocation
attribute becoming an element, add this template too (You will need to declare the xsi
namespace in the XSLT)
<xsl:template match="@xsi:*">
<xsl:copy />
</xsl:template>
Or perhaps you don't want any attributes changed to elements? Try this XSLT instead?
<xsl:stylesheet version="1.0" xmlns:urn="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="*">
<xsl:element name="urn:{local-name()}">
<xsl:apply-templates select="@*|node()" />
</xsl:element>
</xsl:template>
<xsl:template match="@*">
<xsl:copy />
</xsl:template>
<xsl:template match="GBD_Transactions|GBD_Transactions//*|GBD_Transactions//@*">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1
Reputation: 3248
In your template matching "*", you should differentiate like this:
<xsl:template match="*">
<xsl:choose>
<xsl:when test="ancestor-or-self::GBD_Transactions">
<xsl:copy>
<xsl:apply-templates"/>
</xsl:copy>
</xsl:when>
<xsl:otherwise>
<xsl:element name="urn:{local-name()}">
<xsl:apply-templates/>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Output will look like this:
<urn:BatchPrepareDeliverArchive xmlns:urn="http://www.w3.org/2001/XMLSchema-instance">
<urn:BatchInformation>
<urn:RqUId>424000000071256187550913330</urn:RqUId>
<urn:BatchFeedId>CMLTREXT4240</urn:BatchFeedId>
<urn:BatchCount>7</urn:BatchCount>
</urn:BatchInformation>
<urn:BatchDeliverArchive>
<urn:Transactions>
<urn:Transaction>
<urn:TransactionUUID>90022016-01-140000001</urn:TransactionUUID>
<urn:CustomerData>
<GBD_Transactions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<GBD_Transaction>
<Common_Data>
<Transaction_ID>90022016-01-140000001</Transaction_ID>
</Common_Data>
<Templates>
<Template>
<Template_Name>A21_LETTER_FINAL_NOTICE_OF_CANCELLATION_TPA</Template_Name>
<Transaction_ID>90022016-01-140000001</Transaction_ID>
</Template>
</Templates>
</GBD_Transaction>
</GBD_Transactions>
</urn:CustomerData>
<urn:DocInfo>
<urn:Name>OPERATION NAME</urn:Name>
</urn:DocInfo>
</urn:Transaction>
</urn:Transactions>
</urn:BatchDeliverArchive>
</urn:BatchPrepareDeliverArchive>
Is that what you want?
Upvotes: 0