[Home] [By Thread] [By Date] [Recent Entries]
At 2011-03-30 13:50 -0400, Costello, Roger L. wrote:
Hi Folks, First, you don't need to just match on elements with a namespace-uri() because if there isn't one the code still works. Second, it will slow down your transformation, and it isn't elegant at all, but all you have to do is copy all descendent namespace nodes that are not being used. The first step is to do this for elements that are using the namespace except those using the parent's namespace: <xsl:template match="*">
<xsl:element name="{local-name()}" namespace="{namespace-uri()}">
<xsl:for-each select=".//namespace::*">
<xsl:if test="(..//*)[namespace-uri()=current() and
namespace-uri()!=namespace-uri(current()/..)]
<xsl:copy-of select="."/>
</xsl:if>
</xsl:for-each>
<xsl:apply-templates select="@*|node()"/>
</xsl:element>
</xsl:template>Then you have to modify that to include whatever test you need for checking the name. You don't say how specific you need to be, whether you are checking only <t:faultcode> elements or are you checking all elements. The following checks all elements for starting with the prefix ... I have no idea how specific you need to be for poorly formatted text content (e.g. leading spaces): <xsl:template match="*">
<xsl:element name="{local-name()}" namespace="{namespace-uri()}">
<xsl:for-each select=".//namespace::*">
<!-- ( ( find an element using the namespace but
not using the parent's namespace ) or
( find text content beginning with the namespace prefix ) )-->
<xsl:if test="(..//*)[namespace-uri()=current() and
namespace-uri()!=namespace-uri(current()/..)] or
(..|..//*)[starts-with(.,concat(name(current()),':'))]">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:for-each>
<xsl:apply-templates select="@*|node()"/>
</xsl:element>
</xsl:template>Let the processor worry about cleaning up namespace declarations in the result. BTW, although your input is XML well-formed, the prefix you use in your text does not match the SOAP namespace declaration. I'll assume that is an oversight and that you don't want to do case conversion and that you would rather have the text as the same case as the namespace prefix. And, why are you bothered about superfluous namespaces? There is no XML processing reason for getting rid of them. And why restrict yourself to XSLT 1 when XSLT 2 can make this more succinct? I hope this helps. . . . . . . . . . Ken ~/t/ftemp $ cat roger.xml
<t:Test xmlns:t="http://www.test.org"
xmlns:unused="http://www.unused.org"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><t:faultcode>soap:client</t:faultcode> </t:Test> ~/t/ftemp $ xslt roger.xml roger.xsl <?xml version="1.0" encoding="utf-8"?><Test xmlns="http://www.test.org" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <faultcode>soap:client</faultcode> </Test>~/t/ftemp $
~/t/ftemp $ cat roger.xsl
<?xml version="1.0" encoding="US-ASCII"?>
<?xml-stylesheeta href="abc.xsl" type="text/xsl"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0"><xsl:template match="@*|node()"><!--identity for all other nodes-->
<xsl:copy>
<xsl:copy-of select=".//namespace::*"/>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template><xsl:template match="*" priority="1">
<xsl:element name="{local-name()}" namespace="{namespace-uri()}">
<xsl:for-each select=".//namespace::*">
<!-- ( ( find an element using the namespace but
not using the parent's namespace ) or
( find text content beginning with the namespace prefix ) )-->
<xsl:if test="(..//*)[namespace-uri()=current() and
namespace-uri()!=namespace-uri(current()/..)] or
(..|..//*)[starts-with(.,concat(name(current()),':'))]">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:for-each>
<xsl:apply-templates select="@*|node()"/>
</xsl:element>
</xsl:template></xsl:stylesheet>~/t/ftemp $
|

Cart



