Reputation: 11
My source file looks like this:
For my target file I have to remove all namespaces and add the following text after the employee tag:
xmlns="x-schema:file:///C:\lavie\tksql\EMPLOYEE-SCHEMA.XML"
I created a XSLT mapping that removes the ns succesfully but I can't get it to add the explicit xmlns statement in each employee tag.
My XSLT:
<xsl:output indent="yes" method="xml" encoding="utf-8" omit-xml-declaration="no"/>
<!-- Stylesheet to remove all namespaces from a document -->
<!-- NOTE: this will lead to attribute name clash, if an element contains
two attributes with same local name but different namespace prefix -->
<!-- Nodes that cannot have a namespace are copied as such -->
<!-- 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>
<!-- template to copy the rest of the nodes -->
<xsl:template match="comment() | text() | processing-instruction()">
<xsl:copy/>
</xsl:template>
Any ideas what to add to the XSLT for adding the explicit xmlns after each employee tag?
Thanks
Yoni
Upvotes: 1
Views: 335
Reputation: 167571
Use
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns1="urn:C:\lavie\tksql\Employee-Schema.Xsd" exclude-result-prefixes="ns1">
then add the template
<xsl:template match="ns1:employee | ns1:employee//*">
<xsl:element name="{local-name()}" namespace="x-schema:file:///C:\lavie\tksql\EMPLOYEE-SCHEMA.XML">
<xsl:apply-templates select="@* | node()"/>
</xsl:element>
</xsl:template>
Upvotes: 1
Reputation: 163342
XSLT operates on the XPath/XDM data model, and namespace declarations are not part of that model. Instead, namespaces manifest themselves in two ways: by the fact that element and attribute names have three parts (prefix, namespace uri, and local name), and by the fact that elements have namespace nodes.
Usually (including in this case, I believe) you shouldn't be worrying about namespace nodes or namespace declarations: if you generate elements with the correct three-part name, the namespace declarations will take care of themselves when the result tree is serialized.
When you're using xsl:element, you can control the three-part name of the generated element in one of two ways:
(1) <xsl:element name="pre:local"/>
puts the element in the namespace that is bound (in the stylesheet) to the prefix "pre". This is the form to use if you know what namespace is required statically.
(2) <xsl:element name="local" namespace="{$ns}"/>
is useful when the namespace is computed dynamically (at run-time).
Upvotes: 1
Reputation: 8058
Note: Since XML Namespaces inherit to child (contained) elements, an XML serializer may decide not to output redundant declarations. If your XSLT processor has that bit of optimization, you may find that it isn't possible to put an explicit xmlns= on every element using this tool.
Of course since XML namespaces do inherit to child elements, it isn't clear why you think you need to re-declare the namespace binding on every element. All you really need is for all of them to be bound to that namespace... which Martin's answer will do for you.
Upvotes: 0