Rename the root node in xml using xslt - xslt

I am new to xslt and was trying to find a solution to my problem below.
I have a xml, and using xslt I need to do the following
just rename the root node to something else (without copying the entire structure of root node into another tag)
Get rid of the namespaces information in nodes/elements/attributes
Below is my XML
<lbl:ABCD>
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:lbl="http://abc.xyz.com/abc/xsd/sdf/aaaa"
xsi:schemaLocation="http://abc.ayx.com/sdf/xsd/label/efr efr.xsd">
<lbl:Title>title</lbl:Title>
<lbl:date>01/Aug/2018</lbl:date>
<lbl:id>12345</lbl:id>
<lbl:location>0362</lbl:location>
<lbl:Status>aaaa</lbl:status>
<lbl:hashnum>11801792113759009</lbl:hashnum>
</lbl:ABCD>
The output I want to achieve is
<shp>
<Title>title</Title>
<date>01/Aug/2018</date>
<id>12345</id>
<location>0362</location>
<Status>aaaa</status>
<hashnum>11801792113759009</hashnum>
</shp
>
But so far I have been able to manage below (which is not how I need it to be)
<?xml version="1.0" encoding="utf-16"?>
<shp xmlns:lbl="http://abc.xyz.com/abc/xsd/sdf/aaaa">
<lbl:ICNLabel
xsi:schemaLocation="http://abc.ayx.com/sdf/xsd/label/efr efr.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<lbl:Title>title</lbl:Title>
<lbl:date>01/Aug/2018</lbl:date>
<lbl:id>12345</lbl:id>
<lbl:location>0362</lbl:location>
<lbl:Status>aaaa</lbl:Status>
<lbl:hashnum>11801792113759009</lbl:hashnum>
</lbl:ICNLabel>
</shp>
Can someone guide me to resolve this?

XML: (namespaces needs to address at root element)
<lbl:ABCD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:lbl="http://abc.xyz.com/abc/xsd/sdf/aaaa"
xsi:schemaLocation="http://abc.ayx.com/sdf/xsd/label/efr efr.xsd">
<lbl:Title>title</lbl:Title>
<lbl:date>01/Aug/2018</lbl:date>
<lbl:id>12345</lbl:id>
<lbl:location>0362</lbl:location>
<lbl:Status>aaaa</lbl:Status>
<lbl:hashnum>11801792113759009</lbl:hashnum>
</lbl:ABCD>
XSLT:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:lbl="http://abc.xyz.com/abc/xsd/sdf/aaaa">
<xsl:template match="*">
<xsl:element name="{local-name()}"><!--avoiding namespaces-->
<xsl:apply-templates select="#* | node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="#*">
<xsl:attribute name="{local-name()}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
<xsl:template match="comment()">
<xsl:comment>
<xsl:value-of select="."/>
</xsl:comment>
</xsl:template>
<xsl:template match="/*">
<xsl:element name="shp">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
OutPut:
<?xml version="1.0" encoding="UTF-8"?><shp>
<Title>title</Title>
<date>01/Aug/2018</date>
<id>12345</id>
<location>0362</location>
<Status>aaaa</Status>
<hashnum>11801792113759009</hashnum>
</shp>

Related

xslt attributes are not getting copied

This is my xml, I have simple XSLT to update just one element and copy everything else same.
<?xml version='1.0' encoding='UTF-8'?>
<sip xmlns="urn:x-emc:ia:schema:sip:1.0">
<dss>
<holding>message</holding>
<id>message-2018-06-12-gthlZYrWZjJuQ</id>
<pdi_schema>urn:bhp:documentum:message.1.0</pdi_schema>
<production_date>2018-06-12T21:23:04.752+08:00</production_date>
<base_retention_date>2018-06-12T21:23:04.752+08:00</base_retention_date>
<producer>IA_Samples</producer>
<entity>IA</entity>
<priority>0</priority>
<application>IA</application>
</dss>
<production_date>2018-06-12T21:23:04.752+08:00</production_date>
<seqno>1</seqno>
<is_last>true</is_last>
<aiu_count>10</aiu_count>
<page_count>0</page_count>
<pdi_hash algorithm="SHA-256" encoding="base64">iLrzH22nT7Nr258E/oBve+dFDFFyUaMHGz2v9BoBSr0=</pdi_hash>
</sip>
Below is my XSLT
<?xml version="1.0"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="urn:x-emc:ia:schema:sip:1.0" xmlns:exsl="http://exslt.org/common"
xmlns:emc="urn:x-emc:ia:schema:sip:1.0"
extension-element-prefixes="exsl" xmlns:f="Functions" exclude-result-prefixes="emc xs xsl f">
<!-- template to copy elements -->
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:apply-templates select="node()" />
</xsl:element>
</xsl:template>
<!-- template to copy attributes -->
<xsl:template match="#*">
<xsl:attribute name="{local-name()}">
<xsl:value-of select="." />
</xsl:attribute>
</xsl:template>
<xsl:template match="emc:base_retention_date">
<base_retention_date>2016-06-30</base_retention_date>
</xsl:template>
</xsl:stylesheet>
In the output xml the attributes of below elements are not getting copied
<pdi_hash algorithm="SHA-256" encoding="base64">iLrzH22nT7Nr258E/oBve+dFDFFyUaMHGz2v9BoBSr0=</pdi_hash>
What am I missing?
The attributes aren't being copied because you aren't copying them.
If you want to copy attributes using a template rule with match="#*" then you need to ensure that the template is actually invoked, by doing <xsl:apply-templates select="#*"/>.

XSLT2.0 giving empty output when Input XML is having namespcaes

The requirement is to find the duplicate element(BaseName) in XML and marked the parent element(Account) with isDuplicate attribute. The XSL is working correctly when the input XML RootElement has no namespaces. When the root element has namespace then I get empty object. I am not sure why the namespace is causing XSL to generate empty output. Any help to get the right output would be greatly appreciated.`
Input XML WITH NAMESPACE
<?xml version="1.0"?>
<objects xmlns="urn:s.sexmaple.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Account>
<Id>001A00F</Id>
<RecordTypeId>012A00</RecordTypeId>
<BaseName>EFGH</BaseName>
</Account>
<Account>
<Id>001A0</Id>
<RecordTypeId>012A0</RecordTypeId>
<BaseName>ABCD</BaseName>
</Account>
<Account>
<Id>001A</Id>
<RecordTypeId>012A</RecordTypeId>
<BaseName>ABCD</BaseName>
</Account>
</objects>
XSL
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml"
version="1.0"
encoding="UTF-8"
indent="yes"/>
<xsl:strip-space elements="*" />
<xsl:template match="node()|#*">
<xsl:copy copy-namespaces="no">
<xsl:apply-templates select="node()|#*" />
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<xsl:variable name="Accounts">
<objects>
<xsl:for-each select="//Account">
<xsl:sort select="BaseName" />
<xsl:apply-templates select="." />
</xsl:for-each>
</objects>
</xsl:variable>
<xsl:variable name="unqentity">
<objects>
<xsl:for-each select="$Accounts/objects/Account">
<xsl:choose>
<xsl:when test="not(following-sibling::Account/BaseName=./BaseName) and not(preceding-sibling::Account/BaseName=./BaseName) ">
<xsl:copy-of select="." />
</xsl:when>
<xsl:otherwise>
<Account>
<xsl:attribute name="isDuplicate">yes</xsl:attribute>
<xsl:for-each select="child::*">
<xsl:element name="{name()}">
<xsl:copy-of select="#*|node()" />
</xsl:element>
</xsl:for-each>
</Account>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</objects>
</xsl:variable>
<xsl:copy-of select="$unqentity" />
</xsl:template>
</xsl:stylesheet>
Output XML WHEN INPUT XML HAS NAMESPACE
<?xml version="1.0" encoding="UTF-8"?>
<objects/>
Output XML when Input has no Namespaces
<?xml version="1.0" encoding="UTF-8"?>
<objects>
<Account>
<Id>001A00F</Id>
<RecordTypeId>012A00</RecordTypeId>
<BaseName>EFGH</BaseName>
</Account>
<Account isDuplicate="yes">
<Id>001A0</Id>
<RecordTypeId>012A0</RecordTypeId>
<BaseName>ABCD</BaseName>
</Account>
<Account isDuplicate="yes">
<Id>001A</Id>
<RecordTypeId>012A</RecordTypeId>
<BaseName>ABCD</BaseName>
</Account>
</objects>
When you have a namespace, it means the element within the namespace is not the same as an element without a namespace (or indeed an element in a different name space).
This means when you do this in your XSLT...
<xsl:for-each select="//Account">
You are looking for an Account element with no namespace, and so it will not match the Account element in your source XML, which is in the amusingly titled "urn:s.sexmaple.com" (which I suspect is a misspelling)
As you are using XSLT2.0 though, there is a simple way to get around this, by specifying a default namespace for any xpath expressions, using the xpath-default-namespace. Normally, this may be enough, but you have slightly complicated matters by creating new elements within a variable, which you then later try to select.
<xsl:for-each select="$Accounts/objects/Account">
This means when you create the objects and Account elements in the $Accounts variable, they will need to be part of the namespace too.
To cut to the chase, this is what your xsl:stylesheet element needs to look like
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
xmlns="urn:s.sexmaple.com"
xpath-default-namespace="urn:s.sexmaple.com">
So, the xpath-default-namespace="urn:s.sexmaple.com" is used to match elements in your source XML, whilst the xmlns="urn:s.sexmaple.com" is used to ensure the elements you create in the variable have this namespace and can be matched later on.
Having said all that, you have rather over-complicated your whole XSLT. Are you simply trying to add an IsDuplicate attribute to Account elements with the same BaseName? Well, create a key to look up duplicates, like so
<xsl:key name="account" match="Account" use="BaseName" />
Then you can look up duplicates like so:
<xsl:if test="key('account', BaseName)[2]">
<xsl:attribute name="isDuplicate">Yes</xsl:attribute>
</xsl:if>
Try this XSLT, which should give the same results
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xpath-default-namespace="urn:s.sexmaple.com">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="account" match="Account" use="BaseName" />
<xsl:template match="Account">
<xsl:copy>
<xsl:if test="key('account', BaseName)[2]">
<xsl:attribute name="isDuplicate">Yes</xsl:attribute>
</xsl:if>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Note how this only needs to use xpath-default-namespace as it is not creating whole new elements, just copying existing ones (which get their namespace copied across too).
The reason your input XML without a namespace works were the one with a namespace doesn't, isn't because of the input XML, but because of the XSLT stylesheet.
When your XML file has a default namespace, that namespace will need to be declared in the stylesheet itself.
For example, with the following XML:
<test xmlns="test.xml.schema">
<element>Content</element>
</test>
When I apply the following XSLT:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:template match="/">
<out>
<namespace>None</namespace>
<xsl:apply-templates />
</out>
</xsl:template>
<xsl:template match="test">
<test out="True">hello</test>
</xsl:template>
<xsl:template match="*"/>
</xsl:stylesheet>
The output is just:
<out><namespace>None</namespace></out>
The <xsl:template match="test"> can't match on the test element in the input xml, as it is actually test.xml.schema:test while the match in the stylesheet, with no namespace is actually :test. Thus no match is possible.
However, when we just add a namespace for the input document adn modify the template, like so:
<xsl:stylesheet xmlns:t="test.xml.schema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:template match="/">
<out>
<namespace>test.xml.schema</namespace>
<xsl:apply-templates />
</out>
</xsl:template>
<xsl:template match="t:test">
<test out="True">hello</test>
</xsl:template>
<xsl:template match="*"/>
</xsl:stylesheet>
The output becomes:
<out xmlns:t="test.xml.schema">
<namespace>test.xml.schema</namespace>
<test out="True">hello</test>
</out>
Its important to note that the namespace abbreviation in the input document and XSL don't need to be the same (eg. blank vs. "t"), but the namespaces themselfs do: (e.g both blank and "t" must be bound to test.xml.schema).
Also note, that using a default namespace in XSLT can be fraught with issues. So its best to use declared namespaces in XSLT.

How to iterate each xml tag having different names and values ? How to start iterating from a particular tag ? in xslt 2.0

I have the below xml text,
<SUBSCRIBER>
<Anumber>639081000000</Anumber>
<FirstCallDate>20130430104419</FirstCallDate>
<SetyCode>TNT</SetyCode>
<Status>ACT</Status>
<RoamIndicator/>
<PreloadCode>P1</PreloadCode>
<CreationDate>20130116100037</CreationDate>
<PreActiveEndDate/>
<ActiveEndDate>20130804210541</ActiveEndDate>
<GraceEndDate>20140502210541</GraceEndDate>
<RetailerIndicator/>
<OnPeakAccountID>9100</OnPeakAccountID>
<OnPeakSmsExpDate>20130804210504</OnPeakSmsExpDate>
<UnivWalletAcc/>
<UnliSmsOnCtl>20130606211359</UnliSmsOnCtl>
<UnliSmsTriCtl/>
<UnliSmsGblCtl/>
<UnliMocOnCtl>20130606211359</UnliMocOnCtl>
<UnliMocTriCtl/>
<UnliMocGblCtl/>
<UnliSurfFbcCtl>20130606212353</UnliSurfFbcCtl>
</SUBSCRIBER>
How can I iterate/parse over each xml tag name and get the value ( I need the name of the tag and value in a different variables) ? And also, How can I start iterating from particular tag name ? Ex: I would like to start iterating UnivWalletAcc
Please advise.
So far, I have tried the following,
<xsl:template match="SUBSCRIBER">
<xsl:variable name="tagName">
<xsl:value-of select="/*/*/name()"/>
</xsl:variable>
<xsl:variable name="tagValue">
<xsl:value-of select="/*/*/text()"/>
</xsl:variable>
<xsl:value-of select="$tagName"/>
<xsl:value-of select="$tagValue"/>
</xsl:template>
As an alternative to Veenstra's solution, instead of the xsl:if in the SUBSCRIBER/* template, you can control the iteration in the apply-templates:
<xsl:template match="SUBSCRIBER">
<data>
<xsl:apply-templates select="UnivWalletAcc,
UnivWalletAcc/following-sibling::*" />
</data>
</xsl:template>
With the following XSLT you can loop through all childs of the node SUBSCRIBER:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<!-- Identity template that will loop over all nodes and attributes -->
<xsl:template match="#*|node()">
<xsl:apply-templates select="#*|node()" />
</xsl:template>
<!-- Template to match the root and create new root -->
<xsl:template match="SUBSCRIBER">
<data>
<xsl:apply-templates select="#*|node()" />
</data>
</xsl:template>
<!-- Template to loop over all childs of SUBSCRIBER node -->
<xsl:template match="SUBSCRIBER/*">
<!-- This will test if we have seen the UnivWalletAcc node already, if so, output something, otherwise, output nothing -->
<xsl:if test="preceding-sibling::UnivWalletAcc or self::UnivWalletAcc">
<tag>
<tagName><xsl:value-of select="name()" /></tagName>
<tagValue><xsl:value-of select="." /></tagValue>
</tag>
</xsl:if>
</xsl:template>
</xsl:stylesheet>

XSLT: Add namespace to root element

I need to change namespaces in the root element as follows:
input document:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<foo xsi:schemaLocation="urn:isbn:1-931666-22-9 http://www.loc.gov/ead/ead.xsd"
xmlns:ns2="http://www.w3.org/1999/xlink" xmlns="urn:isbn:1-931666-22-9"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
desired output:
<foo audience="external" xsi:schemaLocation="urn:isbn:1-931666-22-9
http://www.loc.gov/ead/ead.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="urn:isbn:1-931666-22-9">
I was trying to do it as I copy over the whole document and before I give any other transformation instructions, but the following doesn't work:
<xsl:template match="* | processing-instruction() | comment()">
<xsl:copy copy-namespaces="no">
<xsl:for-each select=".">
<xsl:attribute name="audience" select="'external'"/>
<xsl:namespace name="xlink" select="'http://www.w3.org/1999/xlink'"/>
</xsl:for-each>
<xsl:copy-of select="#*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
Thanks for any advice!
XSLT 2.0 isn't necessary to solve this problem.
Here is an XSLT 1.0 solution, which works equally well as XSLT 2.0 (just change the version attribute to 2.0):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xlink="http://www.w3.org/1999/xlink"
exclude-result-prefixes="xlink"
>
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*">
<xsl:element name="{name()}" namespace="{namespace-uri()}">
<xsl:copy-of select=
"namespace::*
[not(name()='ns2')
and
not(name()='')
]"/>
<xsl:copy-of select=
"document('')/*/namespace::*[name()='xlink']"/>
<xsl:copy-of select="#*"/>
<xsl:attribute name="audience">external</xsl:attribute>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
When the above transformation is applied on this XML document:
<foo
xsi:schemaLocation="urn:isbn:1-931666-22-9 http://www.loc.gov/ead/ead.xsd"
xmlns:ns2="http://www.w3.org/1999/xlink"
xmlns="urn:isbn:1-931666-22-9"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
the wanted result is produced:
<foo xmlns="urn:isbn:1-931666-22-9"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xlink="http://www.w3.org/1999/xlink"
xsi:schemaLocation="urn:isbn:1-931666-22-9 http://www.loc.gov/ead/ead.xsd"
audience="external"/>
You should really be using the "identity template" for this, and you should always have it on hand. Create an XSLT with that template, call it "identity.xslt", then into the current XSLT. Assume the prefix "bad" for the namespace you want to replace, and "good" for the one you want to replace it with, then all you need is a template like this (I'm at work, so forgive the formatting; I'll get back to this when I'm at home): ... If that doesn't work in XSLT 1.0, use a match expression like "*[namespace-uri() = 'urn:bad-namespace'", and follow Dimitre's instructions for creating a new element programmatically. Within , you really need to just apply-template recursively...but really, read up on the identity template.

Changing a namespace value in an XSL transformation?

I'm not sure if that is possible, as I'm very new to XSLT and stuff, but maybe some of you could help me here? It's a bit tricky and I haven't found anything like it on the internet:
The problem is that I have an input xml with namespaces declared and all and I only need to make slight changes to it (adding or deleting attributes, or shifting them to other locations). But at the same time, I have to update the namespace references in the document's document tag. So, for example, the input xml might look something like this:
<order
xmlns="some.url.01"
xmlns:ns2="some.other.url"
xmlns:ns3="another.one"
>
<orderEntry>
<orderControl>
<mandant>test</mandant>
<businessUnit>test</businessUnit>
<inboundChannel>test</inboundChannel>
<timestamp>timestamp</timestamp>
<requestedDocuments>
<ns2:document>orderForm</ns2:document>
</requestedDocuments>
</orderControl>
</orderEntry>
</order>
the resulting xml should look like this:
<order
xmlns="some.url.02"
xmlns:ns2="some.other.url.02"
xmlns:ns3="another.one.02"
>
<orderEntry>
<orderControl>
<mandant>test</mandant>
<businessUnit>test</businessUnit>
<inboundChannel>test</inboundChannel>
<!-- deleted timestamp for example -->
<requestedDocuments>
<ns2:document>orderForm</ns2:document>
</requestedDocuments>
</orderControl>
</orderEntry>
</order>
but the only thing I get is:
<order
xmlns="some.url.02"
>
<orderEntry>
<orderControl>
<mandant>test</mandant>
<businessUnit>test</businessUnit>
<inboundChannel>test</inboundChannel>
<!-- deleted timestamp for example -->
<requestedDocuments>
<ns2:document xmlns:ns2="some.other.url.02">orderForm</ns2:document>
</requestedDocuments>
</orderControl>
</orderEntry>
</order>
Now maybe for one or two of you it might not be that big a deal, but I have the restriction that the output document should look one-to-one the same as the input document except for the requested changes (namespace changes and deletion).
My XSLT looks a like this:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="some.url.02"
xmlns:ns2="some.other.url.02"
xmlns:ns3="another.one.02"
>
<xsl:output method="xml" version="1.0" encoding="UTF-8" standalone="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="*">
<xsl:choose>
<xsl:when test="name(.) != 'timestamp'">
<xsl:element name="{node-name(.)}">
<xsl:apply-templates select="#*|node()"/>
</xsl:element>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template match="#*">
<xsl:attribute name="{node-name(.)}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
Can somebody please help? Namespaces are tricky :(
P.S.: Whoever edited my entry: Thanks :)
You can set the namespace on the output element with the namespace attribute:
<xsl:element name="{node-name(.)}" namespace="http://www.bar.org">
// ...
</xsl:element>
Note that the namespace must be a URI and although I expect you know this it's probably a good idea to use URIs in your example.
Here is a link to the excellent ZVON tutorial which has worked examples:
http://www.zvon.org/xxl/XSLTreference/Output/xslt_element_namespace.html
I agree that namespaces are tricky. As you know the prefix is semantically irrelevant, but many systems allow you to choose your prefix for aesthetic reasons. Also look at Saxon (http://saxon.sourceforge.net/)
EDIT I think you will find your answer here:
XSLT root tag namespace instead of element attribute namespace
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ns1_src="some.url.01"
xmlns:ns2_src="some.other.url"
xmlns:ns3_src="another.one"
xmlns="some.url.02"
xmlns:ns2="some.other.url.02"
xmlns:ns3="another.one.02"
>
<!--
Note that all the source namespaces got their own new "*_src" prefix.
The target namespaces take over the original prefixes.
"some.url.02" is the new global namespace.
-->
<xsl:output method="xml" version="1.0" encoding="UTF-8" standalone="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- the identity template to copy everything, unless
it has been declared otherwise -->
<xsl:template match="node() | #*">
<xsl:copy>
<xsl:apply-templates select="node() | #*" />
</xsl:copy>
</xsl:template>
<!-- three templates to handle elements -->
<xsl:template match="ns1_src:*">
<xsl:element name="{local-name()}">
<xsl:apply-templates select="node() | #*" />
</xsl:element>
</xsl:template>
<xsl:template match="ns2_src:*">
<xsl:element name="ns2:{local-name()}">
<xsl:apply-templates select="node() | #*" />
</xsl:element>
</xsl:template>
<xsl:template match="ns3_src:*">
<xsl:element name="ns3:{local-name()}">
<xsl:apply-templates select="node() | #*" />
</xsl:element>
</xsl:template>
<!-- three templates to handle attributes -->
<xsl:template match="#ns1_src:*">
<xsl:attribute name="{local-name()}">
<xsl:value-of select="." />
</xsl:attribute>
</xsl:template>
<xsl:template match="#ns2_src:*">
<xsl:attribute name="ns2:{local-name()}">
<xsl:value-of select="." />
</xsl:attribute>
</xsl:template>
<xsl:template match="#ns3_src:*">
<xsl:attribute name="ns3:{local-name()}">
<xsl:value-of select="." />
</xsl:attribute>
</xsl:template>
<!-- timestamps will be ignored -->
<xsl:template match="ns1_src:timestamp" />
</xsl:stylesheet>
Output:
<order xmlns="some.url.02">
<orderEntry>
<orderControl>
<mandant>test</mandant>
<businessUnit>test</businessUnit>
<inboundChannel>test</inboundChannel>
<requestedDocuments>
<ns2:document xmlns:ns2="some.other.url.02">orderForm</ns2:document>
</requestedDocuments>
</orderControl>
</orderEntry>
</order>
<xsl:template match="a:*">
<xsl:element name="{local-name()}"
namespace="http://example.com/B">
<xsl:copy-of select="#*" />
<xsl:apply-templates />
</xsl:element>
</xsl:template>
It searches for any element in namespace with prefix a and replaces it with an element with the same name of namespace http://example.com/B. All attributes are copied 'as is' and then all children are evaluated.
Add your custom processing in or around that as needed.
Are you using Ant's XSLT task to do your transformation?
If the answer is yes, you may want to switch from the default XSLT engine that comes with Sun JDK 1.5+. Read this.
Also, read this article about namespaces in XSLT