xsl-list
[Top] [All Lists]

Multiple level filtering with XSLT

2004-07-22 08:29:15
++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Please read the disclaimer at the bottom of this e-mail.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Hello,

I am developing a generic filtering stylesheet that needs to apply any number 
of filters to an XML data source. The filters can be applied at any level of 
the hierarchy. 

On to the example... Say I have an XML file (see below) that I need to filter. 
I want to filter out 'c' elements where '@x=1' and I also want to filter out 
'd' elements where '@x>=7'. Problem is that when the 'd' elements are filtered 
out, I am left with a 'c' element that contains no 'd' elements, this is not 
allowed according to the XSD (must have at least 1 'c' in each 'd').

Please note:
* I have no access to modify the XSDs
* Filtering at any other step in the process (DB/xml source generation) is not 
an option I have available.

To illustrate my example:
Start with the following XML file
<a x="1">
 <b x="1">
  <c x="1">
   <d x="1"/>
   <d x="2"/>
  </c>
  <c x="2">
   <d x="3"/>
   <d x="4"/>
   <d x="5"/>
  </c>
  <c x="3">
   <d x="6"/>
   <d x="7"/>
  </c>
  <c x="4">
   <d x="8"/>
   <d x="9"/>
  </c>
 </b>
</a>

After applying my XSL I end up with the following. Note the empty 'c' element. 
I somehow need to exclude the 'c' elements that have had all their 'd' elements 
filtered out.
<a x="1">
 <b x="1">
  <c x="2">
   <d x="3"/>
   <d x="4"/>
   <d x="5"/>
  </c>
  <c x="3">
   <d x="6"/>
  </c>
  <c x="4" />
 </b>
</a>

The XSL that I have currently (below) will work well if filtering occurs at the 
same level, but will not work reliably when filtering occurs at multiple levels.
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; version="1.0">
    <xsl:template match="*">
        <xsl:choose>
                <!-- first filter -->
            <xsl:when test="local-name()='c'">
                <xsl:if test="not(@x=1)">
                    <xsl:copy>
                        <xsl:copy-of select="@*"/>
                        <xsl:apply-templates/>
                    </xsl:copy>
                </xsl:if>
            </xsl:when>
                <!-- second filter -->
            <xsl:when test="local-name()='d'">
                <xsl:if test="not(@x&gt;=7)">
                    <xsl:copy>
                        <xsl:copy-of select="@*"/>
                        <xsl:apply-templates/>
                    </xsl:copy>
                </xsl:if>
            </xsl:when>
            <xsl:otherwise>
                <xsl:copy>
                    <xsl:copy-of select="@*"/>
                    <xsl:apply-templates/>
                </xsl:copy>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>


Any help or guidance would be greatly appreciated!

Thanks,
Jeff.


**********************************************************************
This email is intended for the named recipient(s) only. Its contents
are  confidential and may only be retained by the named recipient(s)
and may only be copied or  disclosed  with the consent of 
LCH.Clearnet Limited.   If you are not an intended recipient please
delete this e-mail and notify postmaster(_at_)lchclearnet(_dot_)com(_dot_)

The contents  of this  email are  subject to  contract in all cases, 
and LCH.Clearnet Limited makes no contractual commitment save where
confirmed by hard copy.  LCH.Clearnet Limited accepts no liability, 
including liability for negligence, in respect of any statement in 
this email.

LCH.Clearnet Limited, Registered Office: Aldgate House, 
33 Aldgate High Street, London EC3N 1EA.    Recognised as a Clearing 
House under the Financial Services & Markets Act 2000. Reg in England No.25932 
Telephone: +44 20 7426 7000              Internet: http://www.lchclearnet.com
**********************************************************************



<Prev in Thread] Current Thread [Next in Thread>