xsl-list
[Top] [All Lists]

Re: [xsl] How to remove (in addition) empty attributes?

2009-12-03 15:19:32
(I sent this before but for some reason it seems to have been lost -- apologies if it turns up twice.)

Ben,

As so often, the problem here is in the specification.

You have solved the problems of removing elements according to one rule:

1. elements that have no content (child nodes)

and of attributes according to another:

2. attributes that have no value

but not of removing elements defined as "empty" according to a third:

3. elements that contain only elements and attributes that would removed (by any rule).

You do infer that since your third rule is recursive, a full solution will also be recursive.

If you can rewrite rule 3 so it doesn't invoke itself, you can write a transform that doesn't have to process its own results recursively. For example, you might say:

3a. elements none of whose attributes have values and whose children are empty (have no children)

-- but of course 3a will fail if your containment of such elements goes deeper than two.

Here's a recursive solution (note: XSLT 2.0 only). It works by passing the tree through a set of "scrubbing" templates, and also through a set of copying templates, repeating as necessary until both results are the same. It assumes you don't have any whitespace-only text nodes you want to preserve:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
  xmlns:xs="http://www.w3.org/2001/XMLSchema"; exclude-result-prefixes="xs"
  version="2.0">

<xsl:output indent="yes"/>

<xsl:strip-space elements="*"/>

<xsl:template match="/|*|@*|text()" mode="copy scrub">
  <xsl:copy>
    <xsl:apply-templates select="*|@*|text()" mode="#current"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="*[empty(*|text()|@*[normalize-space()])]" mode="scrub"/>

<xsl:template match="@*[not(normalize-space())]" mode="scrub"/>

<xsl:template match="/">
  <xsl:variable name="scrubbed">
    <xsl:apply-templates select="." mode="scrub"/>
  </xsl:variable>
  <xsl:variable name="copied">
    <xsl:apply-templates select="." mode="copy"/>
  </xsl:variable>
  <xsl:choose>
    <xsl:when test="deep-equal($scrubbed, $copied)">
      <xsl:sequence select="$scrubbed"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:apply-templates select="$scrubbed"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

</xsl:stylesheet>


Tested only lightly....

Cheers,
Wendell

At 02:40 AM 12/3/2009, you wrote:
The problem with this is that only elements OR attributes are stripped but not both at the same time.

Assume the following XML source:

<ns11:elem1 myattr="">
   <ns22:subelem2 />
   <ns22:subelem3></ns22:subelem3>
</ns11:elem1>

Then applying the XSLT script below will result in

<ns11:elem1>
</ns11:elem1>

As you can see the ns11:elem1 persists.
It is handled only in the remove attribute template and does not match the other remove-empty-element template.

So how can I iteratively/recursively re-apply the script/templates on the result again?


XSLT script:

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

  <xsl:output indent="yes"/>

  <xsl:template match="@*[normalize-space(.)='']"/>

  <xsl:template match="*[not(node())]"/>

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

</xsl:stylesheet>

On Wed, 2 Dec 2009 20:58:11 -0500, Syd Bauman wrote:

>How about matching the empty attributes and not generating any
>output?

>  <xsl:template match="@*[normalize-space(.)='']"/>


>> How can I delete empty attributes as well?


======================================================================
Wendell Piez                            
mailto:wapiez(_at_)mulberrytech(_dot_)com
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
======================================================================


--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--