[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

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

Subject: Re: How to remove (in addition) empty attributes?
From: Wendell Piez <wapiez@xxxxxxxxxxxxxxxx>
Date: Thu, 03 Dec 2009 14:33:36 -0500
Re:  How to remove (in addition) empty attributes?
(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@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

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.