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

How to efficiently remove "a" nodes with no "b" descen

Subject: How to efficiently remove "a" nodes with no "b" descendants
From: Teppo Peltonen <teppo.peltonen@xxxxxx>
Date: 08 Mar 2001 17:37:06 +0200
remove node in xml sax
Hello everybody,

I would like to find an efficient way to remove elements of type "a"
which have no descendants of type "b" from an XML structure using XSLT
1.0. 

<!--
Here is an example input:
-->
<a>
   <b/>
   <c/>
   <a>
      <a>
         <a>
            <c>
               <b/>
            </c>
         </a>
         <a>
            <c/>
            <a>
               <c/>
            </a>
         </a>
         <a>      
            <b/>
            <c/>
         </a>
         <c/>
      </a>
      <c/>
   </a>
</a>

<!--
This is the desired output:
-->
<?xml version="1.0" encoding="ISO-8859-1"?>
<a>
   <b></b>
   <c></c>
   <a>
      <a>
         <a>
            <c>
               <b></b>
            </c>
         </a>
         
         <a>      
            <b></b>
            <c></c>
         </a>
         <c></c>
      </a>
      <c></c>
   </a>
</a>

<!--
The obvious way to do it would be using a template like 

<xsl:template match="a[not(.//b)]"/>

However, I wouldn't call that efficient. This becomes a real-world
problem when the input file is large.

Here is a DOM program which seems to do what I want. I just can't
figure out how to do it using XSLT 1.0:
-->

package fi.vtt.tte.pipex.ext;

import java.io.IOException;
import java.util.Properties;
import java.util.Vector;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;

public class Compact2 implements DOMExtension
{
    public Document transform(Document doc, Properties p) throws SAXException, IOException
    {
        Vector v = new Vector();
        prepareNode(doc.getDocumentElement(), v);
        while (!v.isEmpty()) {
            Node n;
            n = (Node)v.firstElement();
            n.getParentNode().removeChild(n);
            v.removeElement(n);
        }
        return doc;
    }

    boolean prepareNode(Node n, Vector v)
    {
        boolean include = false;
        Node child;
        for (child = n.getFirstChild(); child != null; child = child.getNextSibling()) {
           boolean b;
           b = prepareNode(child, v) || "b".equals(child.getNodeName());
           if (!b && "a".equals(child.getNodeName())) {
              v.addElement(child);
           }
           include |= b;
        }
        return include;
    }
}

<!--
I'm starting to feel that I'm missing some trivial solution or *maybe*
this is not possible at all (just trying to provoke you a bit... ;-).

Well, I might as well post my current attempt... This probably is
quite broken:
-->

<?xml version="1.0"?> 

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

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

<xsl:template match="*">
   <xsl:variable name="substr">
      <xsl:apply-templates/>
   </xsl:variable>

   <xsl:variable name="include">
      <xsl:if test="name()='b' or $substr/*/@include='yes'">yes</xsl:if>
   </xsl:variable>

   <xsl:if test="not(name()='a') or $include='yes'">
      <xsl:element name="{name()}">
         <xsl:attribute name="include"><xsl:value-of 
                                    select="$include"/></xsl:attribute>
         <xsl:copy-of select="$substr"/>
      </xsl:element>
   </xsl:if>
</xsl:template>

</xsl:stylesheet>

<!--

Not surprisingly, Xalan says: Can't process Can not convert #UNKNOWN
to a NodeList!

Still there? Thank's a lot for your time,

Teppo

--
Teppo Peltonen <mailto:teppo.peltonen@xxxxxx>     phone 09 4566080
VTT Information Technology                        mobile 040 5651878
Tekniikantie 4 B, P.O.Box 1201, Espoo 02044 VTT   telefax 09 4567052


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


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.