remove child node namespace and copy another node into a variable - xslt

I am trying to copy all the child elements of soap:Header element into a variable and also trying to remove PricingRequest empty namespace (xmlns="http://www.ama.net") and output only PricingRequest part of xml. I am able to remove PricingRequest empty namespace and get proper output but not able to store soap:Header child elements into a variable, is it possible to copy child elements of soap:Header into a variable ?
INPUT XML:
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap ="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header xmlns="http://www.ama.net/1axml-msg/schema/msg-header-1_0.xsd">
<MessageHeader ResponseRequested="true" version="1.0" Terminate="true" Reverse="true" id="09B5581A" soap:mustUnderstand="1">
<From>1ASI</From>
<To>1ASRINSAIG</To>
<TimeStamp>
<GenerationTime>2014-10-22T12:41:38Z</GenerationTime>
</TimeStamp>
</MessageHeader>
</soap:Header>
<soap:Body>
<PricingRequest xmlns="http://www.ama.net">
<originatorSection>
<deliverySystem>
<companyId>1A</companyId>
<cityCode>MUC</cityCode>
</deliverySystem>
</originatorSection>
</PricingRequest>
</soap:Body>
</soap:Envelope>
XSLT :
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:x="http://www.ama.net" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- <xsl:template match="/*[local-name()='Envelope']">
<xsl:variable name="SOAPHeader" select="/soap:Header/node()" />
<xsl:text> MessageHeader INFO:<xsl:copy-of select="$SOAPHeader"/> </xsl:text>
</xsl:template> -->
<xsl:template match="*">
<xsl:element name="{name()}">
<xsl:copy-of select="#*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="*[not(ancestor-or-self::x:PricingRequest)]">
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
getting expecting OUTPUT but not able to copy soap:Header into a variable:
<PricingRequest>
<originatorSection>
<deliverySystem>
<companyId>1A</companyId>
<cityCode>MUC</cityCode>
</deliverySystem>
</originatorSection>
</PricingRequest>

Try;
<xsl:template match="/">
<xsl:variable name="SOAPHeader" select="/soap:Envelope/soap:Header/node()" />
<xsl:text>MessageHeader INFO:</xsl:text>
<xsl:copy-of select="$SOAPHeader"/>
</xsl:template>
Note:
<xsl:text> cannot contain child elements;
your version has conflicting templates for soap:Envelope.

the following code worked the way i wanted. I am able to copy soap:Header child elements in a variable and also removed PricingRequest namespace in the output
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.ama.net/1axml-msg/schema/msg-header-1_0.xsd"
xmlns:ns2="http://www.ama.net" exclude-result-prefixes="ns1 ns2 soap">
<xsl:template match="ns1:* | ns2:*| soap:*">
<xsl:element name="{local-name()}">
<xsl:copy-of select="#*" />
<xsl:apply-templates />
</xsl:element>
</xsl:template>
<xsl:template match="/">
<xsl:variable name="SOAPHeader">
<xsl:apply-templates select="/soap:Envelope/soap:Header/node()" />
</xsl:variable>
<xsl:text>HeaderInfo:</xsl:text>
<xsl:copy-of select="$SOAPHeader" />
<xsl:apply-templates select="/soap:Envelope/soap:Body/node()" />
</xsl:template>
</xsl:stylesheet>
OUTPUT I am getting:
<?xml version="1.0"?>
HeaderInfo:
<MessageHeader xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" ResponseRequested="true" version="1.0" Terminate="true" Reverse="true" id="09B5581A" soap:mustUnderstand="1">
<From>1ASI</From>
<To>1ASRINSAIG</To>
<TimeStamp>
<GenerationTime>2014-10-22T12:41:38Z</GenerationTime>
</TimeStamp>
</MessageHeader>
<PricingRequest>
<originatorSection>
<deliverySystem>
<companyId>1A</companyId>
<cityCode>MUC</cityCode>
</deliverySystem>
</originatorSection>
</PricingRequest>

Related

Sending value with different tag XSLT

is there any chance can sending value to output other node response, with different path from there input request. i have input and response tag like this
Input Request:
<Root>
<Items>
<Item1>Rambutan12</Item1>
</Items>
</Root>
and i try with this code for add new node with additional info at Response
i try like this
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fn="http://www.w3.org/2005/xpath-functions">
<xsl:output method="text"/>
<xsl:template match="/">
<Root>
<ItemsResponse>
<xsl:call-templates select="items">
<xsl:with-param name="item1s" select="//Root/Items/Item1"/>
</xsl:call-templates>
</ItemsResponse>
</Root>
</xst:template>
<xsl:template name="items">
<xsl:param name="item1s"/>
<xsl:variable name="information">
<xsl:choose>
<xsl:when test="fn:matches($item1s, '^[a-zA-Z]*$') ">
<Item1><xsl:value-of select="$item1s"/></Item1>
</xsl:when>
<xsl:otherwise>
<xsl:copy>
<Item1><xsl:value-of select="$item1s"/></Item1>
<xsl:apply-templates select="Item1Information"/>
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
</xsl:template>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="Item1Information">
<xsl:copy>
<Item1Information>Wrong Failed Format Input</Item1Information>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Expected Result was like this
<Root>
<ItemsResponse>
<Item1>Rambutan12</Item1>
<Item1Information>Input Failed Format</ItemInformation>
</ItemsResponse>
</Root>
Any tips like for this case, thanks
It is very difficult to understand what your question is.
On the off-chance that I am guessing correctly, and that you want to add an error warning when Item1 contains any characters other than the 26 letters of the English alphabet, then you could do simply:
XSLT 1.0
<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"/>
<xsl:template match="/Root">
<Root>
<ItemsResponse>
<xsl:copy-of select="Items/Item1"/>
<xsl:if test="translate(Items/Item1, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', '')">
<Item1Information>Input Failed Format</Item1Information>
</xsl:if>
</ItemsResponse>
</Root>
</xsl:template>
</xsl:stylesheet>

XSLT Transformation that add namespace prefix doesn't copy attributes

I have a requirement to add a namespace prefix to all my xml elements.
I have a working xslt for this but unfortunately it doesn't copy the attributes. What do I need to change to also copy these attributes.
This my code:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:ns0="http://ns.hr-xml.org/2007-04-15" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:template match="*">
<xsl:element name="ns0:{local-name()}">
<xsl:apply-templates select="*|node()" />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
The input XML is this:
<HumanResource schemaLocation="http://ns.hr-xml.org/2007-04-15 ../HumanResource.xsd">
<HumanResourceId idOwner="StaffingCompany">
<IdValue>123COMP</IdValue>
</HumanResourceId>
<HumanResourceId idOwner="StaffingCustomer">
<IdValue>456CUST</IdValue>
<!--double hre-id, due fms wnr-code swap-->
</HumanResourceId>
<HumanResourceStatus status="x:Assigned"/>
<ReferenceInformation>
<StaffingSupplierId idOwner="StaffingCustomer">
<IdValue>105964</IdValue>
</StaffingSupplierId>
<StaffingCustomerId idOwner="StaffingCompany">
<IdValue>MIN0000612</IdValue>
</StaffingCustomerId>
<StaffingCustomerId idOwner="StaffingCustomer">
<IdValue>ELI</IdValue>
</StaffingCustomerId>
<StaffingSupplierOrgUnitId idOwner="StaffingCompany">
<IdValue>2606379</IdValue>
</StaffingSupplierOrgUnitId>
<StaffingCustomerOrgUnitId idOwner="StaffingCustomer">
<IdValue>ELI</IdValue>
</StaffingCustomerOrgUnitId>
</ReferenceInformation>
<ResourceInformation>
<PersonName>
<FormattedName>J</FormattedName>
<LegalName>C</LegalName>
<GivenName>J</GivenName>
<PreferredGivenName>J</PreferredGivenName>
<MiddleName>C.J.</MiddleName>
<FamilyName primary="true"></FamilyName>
</PersonName>
<EntityContactInfo>
<EntityName></EntityName>
<PersonName>
<FormattedName>Liesbeth Kramer</FormattedName>
</PersonName>
<ContactMethod>
<Telephone>
<FormattedNumber>070-3102150</FormattedNumber>
</Telephone>
</ContactMethod>
</EntityContactInfo>
<PostalAddress>
<CountryCode>NL</CountryCode>
<PostalCode></PostalCode>
<Municipality></Municipality>
<DeliveryAddress>
<AddressLine></AddressLine>
<StreetName></StreetName>
<BuildingNumber></BuildingNumber>
</DeliveryAddress>
</PostalAddress>
</ResourceInformation>
<Profile/>
<Preferences/>
<UserArea>
<ns2:HumanResourceAdditionalNL xmlns:ns2="http://ns.setu.nl/2008-01">
<ns2:BirthDate>1961-07-13</ns2:BirthDate>
<ns2:Sex>female</ns2:Sex>
</ns2:HumanResourceAdditionalNL>
</UserArea>
</HumanResource>
My result with my code looks like this:
<?xml version='1.0' ?>
<ns0:HumanResource xmlns:ns0="http://ns.hr-xml.org/2007-04-15">
<ns0:HumanResourceId>
<ns0:IdValue>123COMP</ns0:IdValue>
</ns0:HumanResourceId>
<ns0:HumanResourceId>
<ns0:IdValue>456CUST</ns0:IdValue>
</ns0:HumanResourceId>
<ns0:HumanResourceStatus/>
<ns0:ReferenceInformation>
As you can see, the ns0: is added ok but I lost the attributes.
You have lost the attributes because you have no code to select them. You currently do <xsl:apply-templates select="*|node()" />, but * select elements, and node() selects elements, text nodes, comments and processing instructions. You need to change it to this...
<xsl:apply-templates select="#*|node()" />
You would then need a separate template to match attributes and copy them.
<xsl:template match="#*">
<xsl:copy />
</xsl:template>
Try this XSLT
<xsl:stylesheet version="1.0" xmlns:ns0="http://ns.hr-xml.org/2007-04-15" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:template match="*">
<xsl:element name="ns0:{local-name()}">
<xsl:apply-templates select="#*|node()" />
</xsl:element>
</xsl:template>
<xsl:template match="#*">
<xsl:copy />
</xsl:template>
</xsl:stylesheet>
Alternatively, you could use xsl:copy-of to copy the attributes. Try this XSLT too
<xsl:stylesheet version="1.0" xmlns:ns0="http://ns.hr-xml.org/2007-04-15" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:template match="*">
<xsl:element name="ns0:{local-name()}">
<xsl:copy-of select="#*" />
<xsl:apply-templates />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Note that <xsl:apply-templates /> is short-hand for <xsl:apply-templates select="node()" />

XSLT add root node if not exists

I have some XML and having a difficult time transforming it.
Example XML:
<?xml version="1.0" encoding="utf-8"?>
<Cars xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Car> ... </Car>
</Cars>
I would like to change it to:
<?xml version="1.0" encoding="utf-8"?>
<Depot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Cars>
<Car> ... </Car>
</Cars>
</Depot>
Sounds simple enough but the problem is some data is already in the expected format, in which case I don't want to apply the transform. How do I achieve this?
EDIT
Some starting XSLT:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" mlns:xsi="http://www.w3.org/2001/XMLSchema-
instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="Cars">
<Depot>
<Cars>
<xsl:apply-templates select="*"/>
</Cars>
</Depot>
</xsl:template>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
I think you only want to match Cars if it is the root element, so instead of your template matching "Cars", change it to match "/Cars"
<xsl:template match="/Cars">
Try this XSLT (which I have slightly amended to get the first template to call the identity template)
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" >
<xsl:output method="xml" indent="yes" />
<xsl:template match="/Cars">
<Depot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsl:call-template name="identity" />
</Depot>
</xsl:template>
<xsl:template match="#*|node()" name="identity">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
I think that it is just necessary to use a choose in the root template to test if the node Depot exists, if not create it:
<xsl:template match="/">
<xsl:choose>
<xsl:when test="Depot">
<xsl:apply-templates/>
</xsl:when>
<xsl:otherwise>
<Depot>
<xsl:apply-templates/>
</Depot>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()" />
</xsl:copy>
</xsl:template>
This also gives same output.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" >
<xsl:template match="Cars">
<Depot>
<xsl:copy-of select="."/>
</Depot>
</xsl:template>
</xsl:stylesheet>

Generated wrong namespace

Is it possible that the namespace you declare will change if you generate an output? Is it because it gets the last version of this schema?
Below are the namespaces in my schema:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"xmlns:link="http://www.xbrl.org/2003/linkbase"xmlns="http://www.w3.org/2001/XMLSchema" xmlns:xbrli="http://www.xbrl.org/2003/instance" xmlns:gl-cor="http://www.xbrl.org/int/gl/cor/2006-10-25" targetNamespace="http://www.xbrl.org/int/gl/cor/2006-10-25" elementFormDefault="qualified" attributeFormDefault="unqualified">
and the output generated was like this:
<gl-cor:defter xmlns:gl-cor="http://www.xbrl.org/int/gl/cor/2010-04-12" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.xbrl.org/int/gl/cor/2010-04-12 gl-cor-content-2006-10-25.xsd">
if you notice that the namespace of xmlns:gl-cor in the output was changed to "http://www.xbrl.org/int/gl/cor/2010-04-12". I've checked all my files and there's no 2010-04-12 declared. Anyone knows the reason why it happened?
Here is my XSLT:
<?xml version="1.0" encoding="UTF-8"?><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gl-cor="http://www.xbrl.org/int/gl/cor/2010-04-12" xmlns:gl-bus="http://www.xbrl.org/int/gl/bus/2006-10-25" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:link="http://www.xbrl.org/2003/linkbase" xmlns:xbrli="http://www.xbrl.org/2003/instance">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="/gl-cor:defter">
<edefter:defter xmlns:edefter="http://www.edefter.gov.tr"
xmlns:xades="http://uri.etsi.org/01903/v1.3.2#"
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:apply-templates select="#*|node()"/>
</edefter:defter>
</xsl:template>
<xsl:template match="/gl-cor:defter/gl-cor:xbrl">
<xbrli:xbrl
xmlns:iso639="http://www.xbrl.org/2005/iso639"
xmlns:link="http://www.xbrl.org/2003/linkbase"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:gl-plt="http://www.xbrl.org/int/gl/plt/2006-10-25"
xmlns:iso4217="http://www.xbrl.org/2003/iso4217">
<xsl:apply-templates select="#*|node()"/>
</xbrli:xbrl>
</xsl:template>
<xsl:template match="*[ancestor::gl-cor:entityInformation]">
<xsl:element name="gl-bus:{local-name()}">
<xsl:copy-of select="#*" />
<xsl:apply-templates />
</xsl:element>
</xsl:template>
<xsl:template match="*[self::gl-cor:creator]">
<xsl:element name="gl-bus:{local-name()}">
<xsl:copy-of select="#*" />
<xsl:apply-templates />
</xsl:element>
</xsl:template></xsl:stylesheet>
and my xml input file:
<gl-cor:defter xmlns:gl-cor="http://www.xbrl.org/int/gl/cor/2010-04-12" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.xbrl.org/int/gl/cor/2010-04-12 gl-cor-content-2006-10-25.xsd"><gl-cor:xbrl><gl-cor:accountingEntries><gl-cor:documentInfo><gl-cor:creator contextRef="ledger_context"></gl-cor:creator><gl-cor:entityInformation><gl-cor:entityPhoneNumber><gl-cor:phoneNumberDescription contextRef="ledger_context"></gl-cor:phoneNumberDescription>
Your XSLT just copies the input to the output (the first template is an identity transformation).
Since the namespace mappings for the prefix gl-cor are different in the XSLT and the XML input file, none of the other templates will match.

XSLT identity transform produces wrong namespace

I have a custom XML schema that is evolving: elements are added, others deleted, and the namespace changes to reflect the new version (e.g., from "http://foo/1.0" to "http://foo/1.1"). I want to write an XSLT that converts XML documents from the old schema to the new one. My first attempt works, but it's verbose and unscalable, and I need help refining it.
Here's a sample document for the 1.0 schema:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<foo:rootElement xmlns:foo="http://foo/1.0">
<obsolete>something</obsolete>
<stuff>
<alpha>a</alpha>
<beta>b</beta>
</stuff>
</foo:rootElement>
In the 1.1 schema, the "obsolete" element goes away but everything else remains. So the XSLT needs to do two things:
Remove the tag
Change the namespace from http://foo/1.0 to http://foo/1.1
Here's my solution:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:foo1="http://foo/1.0"
xmlns:foo="http://foo/1.1"
exclude-result-prefixes="foo1">
<xsl:output method="xml" standalone="yes" indent="yes"/>
<!-- Remove the "obsolete" tag -->
<xsl:template match="foo1:rootElement/obsolete"/>
<!-- Copy the "alpha" tag -->
<xsl:template match="foo1:rootElement/stuff/alpha">
<alpha>
<xsl:apply-templates/>
</alpha>
</xsl:template>
<!-- Copy the "beta" tag -->
<xsl:template match="foo1:rootElement/stuff/beta">
<beta>
<xsl:apply-templates/>
</beta>
</xsl:template>
<!-- Copy the "stuff" tag -->
<xsl:template match="foo1:rootElement/stuff">
<stuff>
<xsl:apply-templates/>
</stuff>
</xsl:template>
<!-- Copy the "rootElement" tag -->
<xsl:template match="foo1:rootElement">
<foo:rootElement>
<xsl:apply-templates/>
</foo:rootElement>
</xsl:template>
</xsl:stylesheet>
Although this produces the output I want, notice that I have a copying template for every element in the schema: alpha, beta, etc. For complex schemas with hundreds of kinds of elements, I'd have to add hundreds of templates!
I thought I could eliminate this problem by reducing all those copying templates into a single identity transform, like this:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:foo1="http://foo/1.0"
xmlns:foo="http://foo/1.1"
exclude-result-prefixes="foo1">
<xsl:output method="xml" standalone="yes" indent="yes"/>
<xsl:template match="foo1:rootElement/obsolete"/>
<xsl:template match="node()|#*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="foo1:rootElement/stuff">
<xsl:copy>
<xsl:call-template name="identity"/>
</xsl:copy>
</xsl:template>
<xsl:template match="foo1:rootElement">
<foo:rootElement>
<xsl:apply-templates/>
</foo:rootElement>
</xsl:template>
</xsl:stylesheet>
But it produces:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<foo:rootElement xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:foo="http://foo/1.1">
<stuff xmlns:foo="http://foo/1.0">
<stuff>
<alpha>a</alpha>
<beta>b</beta>
</stuff>
</stuff>
</foo:rootElement>
The "stuff" element was copied, which is what I want, but it's wrapped in another "stuff" element, tagged with the old namespace. I don't understand why this is happening. I've tried many ways of fixing this but have been unsuccessful. Any suggestions? Thanks.
This transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="pOldNS" select="'http://foo/1.0'"/>
<xsl:param name="pNewNS" select="'http://foo/1.1'"/>
<xsl:template match="/*">
<xsl:element name="{name()}" namespace="{$pNewNS}">
<xsl:apply-templates select="node()|#*"/>
</xsl:element>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{name()}">
<xsl:copy-of select="namespace::*[not(.=$pOldNS)]"/>
<xsl:apply-templates select="node()|#*"/>
</xsl:element>
</xsl:template>
<xsl:template match="#*">
<xsl:choose>
<xsl:when test="namespace-uri()=$pOldNS">
<xsl:attribute name="{name()}" namespace="{$pNewNS}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="obsolete"/>
</xsl:stylesheet>
when applied on this XML document:
<foo:rootElement xmlns:foo="http://foo/1.0">
<obsolete>something</obsolete>
<stuff>
<alpha x="y" foo:t="z">a</alpha>
<beta>b</beta>
</stuff>
</foo:rootElement>
produces the wanted, correct result (obsolute elements deleted, namespace upgraded, attribute nodes correctly processed, including nodes that were in the old namespace):
<foo:rootElement xmlns:foo="http://foo/1.1">
<stuff>
<alpha x="y" foo:t="z">a</alpha>
<beta>b</beta>
</stuff>
</foo:rootElement>
Main advantages of this solution:
Works correctly when there are attributes, belonging to the old-schema namespace.
General, allows the old and new namespace to be passed as external parameters to the transformation.
While you might want to copy the attributes, elements need to be regenerated in the new namespace. So I'd suggest to do it like this:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:foo1="http://foo/1.0">
<xsl:template match="foo1:rootElement/obsolete"/>
<xsl:template match="attribute()">
<xsl:copy/>
</xsl:template>
<xsl:template match="element()">
<xsl:variable name="name" select="local-name()"/>
<xsl:element name="{$name}" namespace="http://foo/1.1">
<xsl:apply-templates select="node()|#*"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>