XSLT Ignore namespace - xslt

I'm trying to get accustomed to XSLT, and I understand the reason for namespaces, but I'm simply trying to convert local XML files to be consumed by a local application.
I'm trying to convert the file found here: http://uscodebeta.house.gov/download/releasepoints/us/pl/113/31/xml_usc01#113-31.zip
using this code:
<?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" indent="yes" name="xml"/>
<xsl:template match="//title">
<xsl:for-each select="section">
<xsl:variable name="href"><xsl:value-of select="ancestor::title/num/#value" />-<xsl:value-of select="ancestor::chapter/num/#value" />-<xsl:value-of select="num/#value" />.xml</xsl:variable>
<xsl:result-document href="$href">
<xsl:element name="structure">
<xsl:element name="unit">
<xsl:attribute name="label">title</xsl:attribute>
<xsl:attribute name="identifier">
<xsl:value-of select="ancestor::title/num/#value" />
</xsl:attribute>
<xsl:attribute name="order_by">
<xsl:value-of select="ancestor::title/num/#value" />
</xsl:attribute>
<xsl:attribute name="level">1</xsl:attribute>
<xsl:value-of select="ancestor::title/num" /> <xsl:value-of select="ancestor::title/heading"/>
</xsl:element>
</xsl:element>
</xsl:result-document>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
into the XML example found here:
https://github.com/statedecoded/statedecoded/wiki/XML-Format-for-Parser
This is the conversion for just the first element, but when running with Saxon on the command line, I'm getting the warning:
Warning: SXXP0005: The source document is in namespace http://xml.house.gov/schemas/uslm/1.0, but all the template rules match elements in no namespace
and the output is plain text instead of XML tags.
Any help would be greatly appreciated.
Thanks

Since you're using XSLT 2.0 you can add the xpath-default-namespace attribute on xsl:stylesheet. See http://www.w3.org/TR/xslt20/#standard-attributes for more details.
For example:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xpath-default-namespace="http://xml.house.gov/schemas/uslm/1.0">
You also have the option of using * as the prefix for each element in your paths. That could end up being a lot of work though if your stylesheet grows.
Example:
ancestor::*:title/*:num
Full example:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xpath-default-namespace="http://xml.house.gov/schemas/uslm/1.0">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="#*|node()">
<xsl:apply-templates select="#*|node()"/>
</xsl:template>
<xsl:template match="section">
<xsl:result-document href="{ancestor::title/num/#value}-{ancestor::chapter/num/#value}-{num/#value}.xml">
<structure>
<unit label="title" identifier="{ancestor::title/num/#value}"
order_by="{ancestor::title/num/#value}" level="1">
<xsl:value-of select="concat(ancestor::title/num,' ',ancestor::title/heading)"/>
</unit>
</structure>
</xsl:result-document>
</xsl:template>
</xsl:stylesheet>

Related

xspec: failure when expected and result are the same

I use xspec for testing of stylesheets. Most of the time it works fine, but once in a while tests fail without a valid reason: the expected and the actual result are the same. Seemingly: everything is green in the comparison screen.
In that case, I mostly get it working again after trying all kinds of things, but without knowing what change 'did it'.
It would be most helpful if xspec would report the reason of the failure, but if you can help me (instead of the xspec output) to shine some light on this, I'd be very happy.
This is a reduced test case:
xsl:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:uc="http://www.infinity-loop.de/namespace/upcast/4.0/"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:html="http://www.w3.org/HTML/1998/html4"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="uc xlink html xs xsl">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:template match="bezwaar">
<xsl:variable name="content">
<xsl:element name="{name()}">
<xsl:apply-templates select="#*|node()"/>
</xsl:element>
</xsl:variable>
<xsl:copy-of select="$content"/>
</xsl:template>
<xsl:template match="#*" >
<xsl:attribute name="{name()}" namespace="{namespace-uri()}">
<xsl:value-of select="." />
</xsl:attribute>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{name()}" namespace="{namespace-uri()}">
<xsl:apply-templates select="#*|node()" />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
xspec:
<?xml version="1.0" encoding="UTF-8"?>
<x:description
xmlns:x = "http://www.jenitennison.com/xslt/xspec"
stylesheet="file:/home/rdgon/project/kraak/kraak-xslt/publicatiebladen/staatscourant/stcrt_step2.xsl">
<x:param name='ns' select="false()"/>
<x:scenario label='test'>
<x:scenario label='werkt dit'>
<x:context><bezwaar>
<al>Noem in het bezwaarschrift:</al>
<al nadruk="cur">Vergeet niet te ondertekenen.</al>
</bezwaar>
</x:context>
<x:expect>
<bezwaar>
<al>Noem in het bezwaarschrift:</al>
<al nadruk="cur">Vergeet niet te ondertekenen.</al>
</bezwaar>
</x:expect>
</x:scenario>
</x:scenario>
</x:description>
Test report showing failure:
Can you explain what I am failing to see?
Ruud
Because xsl:variable doesn't have #as, your result is a document node. But your x:expect expects an element.
If you want to let your x:expect expect a document node, you need to add select="/" to x:expect. Look for an explanation "If you specify no #select" in XSpec Wiki.
If you have run your XSL then bezwaar Element come 2 times and come extra namespace because you have x:context and x:expect in the same element. if you want to x:expect same as x:context then you can try this code.
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:x = "http://www.jenitennison.com/xslt/xspec"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs x">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="x:scenario">
<xsl:apply-templates select="x:scenario/x:context/bezwaar"/>
</xsl:template>
<xsl:template match="bezwaar">
<xsl:element name="{local-name()}">
<xsl:apply-templates select="#*|node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="al">
<xsl:element name="{local-name()}">
<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>
or if you want bezwaar multiple times then you can comment 1st template match.

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()" />

Remove namespace declaration from XSLT stylesheet with XSLT

I have an XSLT stylesheet like the following:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:XQHeaderFunc="java:com.sonicsw.xq.service.xform.HeaderExtension"
xmlns:saxon="http://saxon.sf.net/">
<saxon:script language="java" implements-prefix="XQHeaderFunc" src="java:com.sonicsw.xq.service.xform.HeaderExtension" />
<xsl:output indent="yes" omit-xml-declaration="yes"/>
<xsl:template match="/">
<xsl:variable name="processId" select="XQHeaderFunc:getProperty(XQHeaderFunc:new(),'processId',-1)" />
<xsl:value-of select="XQHeaderFunc:setProperty(XQHeaderFunc:new(),'processId',string(#id),-1)"/>
<root>
<xsl:apply-templates />
</root>
</xsl:template>
<!-- Other stuff -->
</xsl:stylesheet>
I want to transform this stylesheet using a second XSLT stylesheet to remove anything that has to do with the XQHeaderFunc and saxon namespaces. Is there a way I can do this?
I have now tried the following, which successfully deals with the elements, but the namespace declaration doesn't seem to want to disappear.
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:XQHeaderFunc="java:com.sonicsw.xq.service.xform.HeaderExtension"
xmlns:saxon="http://saxon.sf.net/"
exclude-result-prefixes="XQHeaderFunc saxon">
<xsl:param name="XQHeaderReplacement" />
<xsl:variable name="apos">'</xsl:variable>
<!-- Copy all nodes -->
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<!-- Remove saxon script tag -->
<xsl:template match="saxon:script" />
<!-- Remove elements with setProperty calls -->
<xsl:template match="*[starts-with(#select, 'XQHeaderFunc:setProperty')]" />
<!-- Replace getProperty calls with replacement value-->
<xsl:template match="#select[starts-with(., 'XQHeaderFunc:getProperty')]">
<xsl:attribute name="select">
<xsl:value-of select="concat($apos, $XQHeaderReplacement, $apos)"/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
Output:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:XQHeaderFunc="java:com.sonicsw.xq.service.xform.HeaderExtension"
xmlns:saxon="http://saxon.sf.net/">
<xsl:output indent="yes" omit-xml-declaration="yes" />
<xsl:template match="/">
<xsl:variable name="processId" select="''" />
<root>
<xsl:apply-templates />
</root>
</xsl:template>
<!-- Other stuff -->
</xsl:stylesheet>
I would add
exclude-result-prefixes="foo"
onto your
<xsl:stylesheet>
element. Then the namespace declaration for foo will be omitted if possible, i.e. if there no elements or attributes in that namespace to output.
FYI, the reason tnat this line
<xsl:template match="xsl:stylesheet/#xmlns:foo" />`
throws an error is because xmlns:foo in the input document is not an attribute; it's a pseudoattribute. What your match pattern is asking to match is an attribute named foo that is in a namespace corresponding to a namespace prefix xmlns. Since you have not declared a namespace prefix xmlns in your stylesheet, you get the error "prefix xmlns is not defined."
Update:
I see from your posted output (and my own testing) that exclude-result-prefixes hasn't been effective in removing the namespace declaration.
1) First I would ask why it matters. It doesn't change the namespace of anything in your output XSLT. Are you just trying to remove it for aesthetic reasons?
2) Looking at the XSLT 1.0 spec, it appears to me that <xsl:copy> pays no attention to exclude-result-prefixes:
Instantiating the xsl:copy element creates a copy of the current node.
The namespace nodes of the current node are automatically copied as
well...
AFAICT, only literal result elements will omit namespace nodes based on exclude-result-prefixes.
On that basis, I would try replacing <xsl:copy> in your identity template (for elements) with <xsl:element name="{name()}"> or some variant thereof. You would then need a separate identity template for non-element nodes.
I replaced your identity template with the following two templates:
<!-- Copy elements -->
<xsl:template match="*" priority="-1">
<xsl:element name="{name()}">
<xsl:apply-templates select="node()|#*"/>
</xsl:element>
</xsl:template>
<!-- Copy all other nodes -->
<xsl:template match="node()|#*" priority="-2">
<xsl:copy />
</xsl:template>
and that gave what I believe is the desired output, with no extraneous ns declarations:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output indent="yes" omit-xml-declaration="yes" />
<xsl:template match="/">
<xsl:variable name="processId" select="''" />
<root>
<xsl:apply-templates />
</root>
</xsl:template>
<!-- Other stuff -->
</xsl:stylesheet>
(I have adjusted the whitespace for clarity.)

How to set a namespace prefix to a payload xsl

I have this payload, what I am intresting to know is how i can add this "TV:" namespace prefix to all nodes and elementes in it.
<TVInqResponse>
<TVInqRS>
<StatusCode>0</StatusCode>
<StatusDescription>Success</StatusDescription>
This is what is expect to have as a result:
<**tv**:TVInqResponse>
<**tv**:TVInqRS>
<**tv**:StatusCode>0</**tv**:StatusCode>
<**tv**:StatusDescription>Success</**tv**:StatusDescription>
This transformation:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:tv="some:tv">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="*">
<xsl:element name="tv:{name()}" namespace="some:tv">
<xsl:apply-templates select="#*|node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="#*">
<xsl:attribute name="{name}"><xsl:value-of select="."/></xsl:attribute>
</xsl:template>
</xsl:stylesheet>
when applied on this XML document (based on the malformed provided "playload"...):
<TVInqResponse>
<TVInqRS>
<StatusCode>0</StatusCode>
<StatusDescription>Success</StatusDescription>
</TVInqRS>
</TVInqResponse>
produces the wanted, correct result:
<tv:TVInqResponse xmlns:tv="some:tv">
<tv:TVInqRS>
<tv:StatusCode>0</tv:StatusCode>
<tv:StatusDescription>Success</tv:StatusDescription>
</tv:TVInqRS>
</tv:TVInqResponse>
If you also want any attribute name to be in the same namespace, replace the template matching attributes with this one:
<xsl:template match="#*">
<xsl:attribute name="tv:{name()}" namespace="some:tv">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>

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>