Scott Sauyet wrote:
One of the main things I need to do is change the xmlns:tns attribute.
xmlns:tns is not an attribute but a namespace declaration. It looks like
an attribute but it is not and cannot be handled as one.
I was naive and thought I could do it just by declaring a new one in
my root tag and then mostly doing the identity transform.
In a certain way you are probably right here. But I fail to see what you
mean with "changing the xmlns:tns attribute": do you mean, you want the
namespace of elements in the namespace pointed to by tns: to point to
another namespace? Or do you want the prefix to change? Or something
else perhaps? Do you want to globally replace the namespace belonging to
tns: or only for certain elements?
The root <definitions> tag in the original WSDL has
xmlns:tns="http://tempuri.org/"
Now throughout the document, elements that look like these:
<xs:simpleType name="addrFormat" .../>
<service name="SessionsService" .../>
get transformed into these:
<xs:simpleType xmlns:tns="http://tempuri.org/" name="addrFormat">
<service xmlns:tns="http://tempuri.org/" name="SessionsService">
There is nothing wrong with this. The elements are still the same. The
added namespace does nothing and is probably added by the processor
because there are child elements that use the namespace.
There must be some simple way to control this.
To control what?
Any suggestions? The entire (short) WSDL is below.
I would like to help, but you forgot to paste the WSDL. All you showed
is the XSLT. I'll try to give some comments on that.
<xsl:output method="xml" indent="yes" omit-xml-declaration="no"/>
- the xml declaration is provided by default, specifying this is redundant.
- the output of method xml is the default, specifying this is redundant
(though some consider it good practice to make it explicit)
<xsl:param name="bindings" select="'Service'"/>
you never seem to use this parameter. Did you provide the full XSLT or
did you leave parts out?
<xsl:template match="/wsdl:definitions">
<definitions
targetNamespace="MyNewNamespace"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:tns="@Service@"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:ro="urn:Databox"
>
Just out of curiosity: why do you specify all these namespace
declarations? You do not use them here and you already specified most of
them in the xsl:stylesheet root. This has not additional effect, you can
leave them out. Overriding a namespace (like tns: here) will only have
effect if you use the prefix explicitly from here, it will not change
the namespace of elements that are copied using xsl:copy or xsl:copy-of.
<xsl:template match="wsdl:types">
<types>
Here you remove the namespace information. Is that on purpose? It
changes your WSDL to a non-conformant WSDL.
<xsl:template match="xs:schema">
<xs:schema targetNamespace="urn:Databox" xmlns="urn:Databox">
It looks like you can just as well use xsl:copy here.
<xsl:text>
</xsl:text>
An empty xsl:text has no effect.
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
This is your general identity template. Do note, however, that elsewhere
in your source, you only use bare apply-templates, without a 'select',
which means that you only apply elements, not attributes, nor text
nodes. Is that on purpose? Do you mean to remove the text nodes there,
or there just aren't any?
I have not seen anything in your code where you copy a namespace (but
hey, that was why you asked the question, no?). Here's one way to change
a namespace axis for a whole document, and leaving the rest intact:
<xsl:template match="*[namespace-uri() = 'http://oldnamespace']">
<xsl:element name="{name()}" namespace="http://newnamespace">
<xsl:apply-templates select="@* | node()" />
</xsl:element>
</xsl:template>
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*" />
</xsl:copy>
</xsl:template>
Dealing with the prefix can be done in three ways:
<!-- remove the prefix entirely -->
<xsl:element name="{local-name()}" namespace="http://newnamespace">
<!-- new prefix -->
<xsl:element name="new-prefix:{local-name()}"
namespace="http://newnamespace">
<!-- leave original prefix, but bind it to a new namespace-->
<xsl:element name="{name()}" namespace="http://newnamespace">
Hope this helps,
Cheers,
-- Abel Braaksma