Re: [xsl] How to remove unnecessary "xmlns:xx" attributes?

Subject: Re: [xsl] How to remove unnecessary "xmlns:xx" attributes?
From: Wolfgang Laun <wolfgang.laun@xxxxxxxxx>
Date: Wed, 10 Nov 2010 11:11:13 +0100
If one of the grand wizards would kindly review my solution:


<?xml version="1.0"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>

<xsl:template match="/">
  <xsl:apply-templates select="*"/>
</xsl:template>

<xsl:template match="/node()">
  <xsl:copy copy-namespaces = "no">
    <xsl:for-each-group select = "descendant-or-self::node()"
                        group-by = "node-name(.)">
      <xsl:variable name="key" select="current-grouping-key()"/>
      <xsl:if test="namespace-uri-from-QName($key)">
        <xsl:namespace name="{ prefix-from-QName($key) }">
          <xsl:value-of select="namespace-uri-from-QName($key)"/>
        </xsl:namespace>
      </xsl:if>
    </xsl:for-each-group>
     <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="@*|*">
  <xsl:copy copy-namespaces = "no">
     <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>

</xsl:stylesheet>

Input:
<doc xmlns:abc="a/b/c" xmlns:xyz="x/y/z" xmlns="p/q/r">
  <abc:bef>The quick brown fox jumps over the lazy dog</abc:bef>
  <para doc="jar">a para 1</para>
  <para doc="file">a para 2</para>
  <def:dir xmlns:def="d/e/f" xmlns:uvw="u/v/w">
    <num>4123456</num>
    <num>412345</num>
    <num>41234567</num>
    <ghi:num xmlns:ghi="g/h/i">1242345678</ghi:num>
    <num>4222</num>
  </def:dir>
</doc>

Output:
<?xml version="1.0" encoding="UTF-8"?>
<doc xmlns="p/q/r" xmlns:abc="a/b/c" xmlns:def="d/e/f" xmlns:ghi="g/h/i">
  <abc:bef>The quick brown fox jumps over the lazy dog</abc:bef>
  <para doc="jar">a para 1</para>
  <para doc="file">a para 2</para>
  <def:dir>
    <num>4123456</num>
    <num>412345</num>
    <num>41234567</num>
    <ghi:num>1242345678</ghi:num>
    <num>4222</num>
  </def:dir>
</doc>


On 10 November 2010 00:07, Wendell Piez <wapiez@xxxxxxxxxxxxxxxx> wrote:
>
> David,
>
> I assume we are talking about a stylesheet that would copy all the input
except any namespaces that are not actually used, giving a result document in
which they were not declared.
>
> This is easier to do in XSLT 2.0 than in XSLT 1.0. If you need an XSLT 1.0
solution you should say so.
>
> In XSLT 2.0, this could be accomplished by an stylesheet with an identity
template set with copy-namespaces="no", and a template matching the document
node (top-level element) that would reach into the document, group its
elements and attributes by their namespace (the one actually used), and copy a
namespace node for each group to the document element.
>
> The result would be a document in which each of the namespaces actually used
would be declared at the top level.
>
> Unfortunately I don't have time at the moment to mock this up for you, but
it shouldn't be all that hard, given facilities in XSLT 2.0 (for grouping) and
XPath 2.0 (namespace-uri() and friends, for determining namespaces used in
names).
>
> Keep in mind that additional complications could arise if you ever have
clashing namespaces (same namespace and different prefix or same prefix
different namespace). Hopefully you don't.
>
> Cheers,
> Wendell
>
> At 01:58 PM 11/9/2010, you wrote:
>>
>> I currently have an ad hoc Soap client framework that uses JAXB to
>> marshal a Soap request.  This generates a "minimal" Soap envelope, in
>> that it contains a "xmlns:xx" attribute for every "xx" that is actually
>> referenced in the request.
>>
>> The WSDL that defines this request references numerous schemas, and
>> defines all the possible operations for this service.
>>
>> I'm now doing an experiment to see if I can replace our ad hoc Soap
>> client framework with Apache CXF.  My results so far are ok, but I
>> noticed that the request that is built now contains "xmlns:xx"
>> attributes for EVERY schema referenced in the WSDL, even if that
>> namespace isn't referenced in the request.  As a result, my requests are
>> now 20 times larger.
>>
>> I'm examining whether it's possible to get back to what I had before,
>> although with the new framework, but I think it may not be practical.
>> I'm not even sure the resulting larger request will result in any
>> increased latency.  It might make no difference, from a performance
>> point of view.
>>
>> However, these requests are occasionally saved and passed back and forth
>> in email, to discuss certain operational issues.  It would be ideal if
>> these requests are "minimal".  If I can't solve this problem at runtime,
>> I'd at least like to have an XSLT stylesheet that can "minimize" the
>> request by simply removing the "xmlns:xx" attributes where the namespace
>> referred to by the "xx" prefix is not referenced in the request.  I've
>> googled about this, but I haven't found a clear solution for this.  Does
>> someone have an idea how I would write a stylesheet to do this?
>
>
> ======================================================================
> Wendell Piez                            mailto:wapiez@xxxxxxxxxxxxxxxx
> Mulberry Technologies, Inc.                http://www.mulberrytech.com
> 17 West Jefferson Street                    Direct Phone: 301/315-9635
> Suite 207                                          Phone: 301/315-9631
> Rockville, MD  20850                                 Fax: 301/315-8285
> ----------------------------------------------------------------------
>  Mulberry Technologies: A Consultancy Specializing in SGML and XML
> ======================================================================

Current Thread