Reputation: 13811
I'm using this template for copying without namespace:
<xsl:template match="*" mode="copy-no-namespaces">
<xsl:element name="{local-name()}">
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="node()" mode="copy-no-namespaces"/>
</xsl:element>
</xsl:template>
<xsl:template match="comment()| processing-instruction()" mode="copy-no-namespaces">
<xsl:copy/>
</xsl:template>
this works. But I want it to copy without certain namespace rather than all namespace. For example I want to ignore few namespaces like http://test.com
, http://test2.com
, the copy should remove only these namespaces, not all the namespace.
Example:
<xs:schema xmlns:xxx="http://include.com" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:zzz="http:test.com" >
<zzz:element>
</zzz:element>
<xxx:complexType>
</xxx:complexType>
</xs:schema>
Here zzz
namespace should be removed but preserve xxx
as zzz
only matches http://test.com
, so the output will be
<xs:schema xmlns:xxx="http://include.com" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<element>
</element>
<xxx:complexType>
</xxx:complexType>
</xs:schema>
How can I achieve this?
Upvotes: 0
Views: 2722
Reputation: 116992
I think you may be confusing between moving elements to a different (or no) namespace and copying namespaces (i.e. namespace declarations). You should only need to move the zzz:
prefixed elements to no-namespace - and not care if the output contains a by now redundant namespace declaration:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns1="http:test.com"
exclude-result-prefixes="ns1">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ns1:*">
<xsl:element name="{local-name()}">
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
P.S. If you prefer, you can do the same thing without declaring any prefix:
<xsl:template match="*[namespace-uri()='http:test.com']">
<xsl:element name="{local-name()}">
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
Upvotes: 3
Reputation: 5892
Use a template with higher priority to keep elements in given namespace:
<xsl:template match="*"
mode="copy-no-namespaces">
<xsl:element name="{local-name()}">
<xsl:apply-templates select="node() | @*" mode="copy-no-namespaces"/>
</xsl:element>
</xsl:template>
<xsl:template match="xxx:*" xmlns:xxx="http://include.com"
mode="copy-no-namespaces">
<xsl:element name="{name()}" namespace="{namespace-uri()}">
<xsl:apply-templates select="node() | @*" mode="copy-no-namespaces"/>
</xsl:element>
</xsl:template>
<xsl:template match="node() | @*"
mode="copy-no-namespaces"
priority="-10">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
The first template strips namespaces from elements, the second retains namespace http://include.com
in elements, and the last copies everything else.
The second template could use xsl:copy
instead of xsl:element
, but that would copy all namespaces in scope and you'd end up with redundant namespace declarations.
Upvotes: 0