You are viewing a plain text version of this content. The canonical link for it is here.
Posted to docs@cocoon.apache.org by Apache Wiki <wi...@apache.org> on 2005/09/12 17:03:59 UTC

[Cocoon Wiki] Update of "DP Filtering" by KermagoretJc

Dear Wiki user,

You have subscribed to a wiki page or wiki category on "Cocoon Wiki" for change notification.

The following page has been changed by KermagoretJc:
http://wiki.apache.org/cocoon/DP_Filtering

New page:
= Filtering design pattern =

= Intent =
Some features need configuration files that may vary just a little for different situations. This pattern has beed designed to avoid redundancy (by rewriting almost same files) and complexity (by using XSLT) while resolving these different situations.

A XSLT implementation is provided.

= Motivation =
There are a lot of situations where configuration files only differ a little. To resolve this situation, we may write specific XSLT (or java, ...) code.

To avoid this complexity that decreases maintenance and usability, we may create a filter (like the Role-filter cocoon transformer) in XSLT, that will selects (delete or keeps) elements according the rule provided (and not only the user's role).

For example, if you have the following fragment that describes a form, you may have create and update modes in the same file :



= Usage =
It may be used when you have files that differ only a little. Two elements, in http://bluexml.org/filter/1.0 namespace, are available :

<?xml version="1.0"?>

<root xmlns:filter="">
    <A>
        <filter:keep-current-element when="a"/>
    </A>
    <B>
        <filter:keep-current-element when="nota"/>
    </B>
</root>

It is useful when working with static files. If you dynamically generate your files, generate directly the file you need, I think you will avoid problems.

>>From a performance point of view, there is no impact because you will use it with configuration files that are usually well cached by the system.

= Structure/Architecture =
[img src=""]

= Component =
* filter:tags : tags in filter namespace and processed by the filter
* condition : the condition to encounter to realize the action indicated

= Implementation =
It's a simple XSLT.

<!--|
    | CVS $Id: filter.xsl,v 1.4 2005/08/03 13:41:37 cvsjck Exp $
    |
    | This stylesheet filters elements and deletes or keeps them according they
    | verify the condition or not.
    |
    | @author jck@bluexml.com
    | @copyright 2004-2005 Babel Objects SARL. All rights reserved.
    |-->

<xsl:stylesheet
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:filter="http://bluexml.org/filter/1.0">
    
<!--|
    | Condition
    | Usually user's role, view, ... To be satisfied, the condition parameter
    | must contain (include) the condition given in the @when attribute
    | For example :
    | * condition = role-dataadmin, when = dataadmin => verified
    | * condition = user-anonymous, when = dataadmin => not verified
    |-->
<xsl:param name="condition">sysadmin-create</xsl:param>
<xsl:param name="log">nodebug</xsl:param>

<!--|
    | For each element, we 'reserve' the element and attribute creation
    | We first check each available rule and apply it
    | Finally we eventually copy the others attributes
    | which is not correct.
    |
    | @param @when the condition to verify
    | @returns the node if the condition is verified, nothing otherwise
    |
    | @TODO : the conditions admin-create and create are realized the same way,
    |-->
<xsl:template match="*[filter:delete-current-node]">
    <xsl:variable name="results">
        <xsl:for-each select="filter:delete-current-node">
            <xsl:if test="'debug' = $log">
                When = <xsl:value-of select="@when"/>
            </xsl:if>
            <xsl:if test="contains($condition, @when)">1</xsl:if>
        </xsl:for-each>
    </xsl:variable>
    <xsl:if test="'debug' = $log">
        Results = <xsl:value-of select="$results"/>
        Condition = <xsl:value-of select="$condition"/>
        Result = <xsl:value-of select="contains($condition, @when)"/>
    </xsl:if>
    <xsl:if test="not(contains($results, '1'))">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:if>
</xsl:template>

<xsl:template match="*[filter:keep-current-node]">
    <xsl:variable name="results">
        <xsl:for-each select="filter:keep-current-node">
            <xsl:if test="'debug' = $log">
                When = <xsl:value-of select="@when"/>
            </xsl:if>
            <xsl:if test="contains($condition, @when)">1</xsl:if>
        </xsl:for-each>
    </xsl:variable>
    <xsl:if test="'debug' = $log">
        Results = <xsl:value-of select="$results"/>
        Condition = <xsl:value-of select="$condition"/>
        Result = <xsl:value-of select="contains($condition, @when)"/>
    </xsl:if>
    <xsl:if test="contains($results, '1')">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:if>
</xsl:template>

<!--|
    | build-rtf : builds a rtf <parameters><parameter></parameter></parameters> from parameters provided in query string format
    |-->
<xsl:template name="build-rtf">
    <xsl:param name="parameters"/>
    
    <xsl:for-each select="$parameters">
        <xsl:if test="'' != normalize-space(substring-before(.,'='))">
            <parameter>
                <xsl:attribute name="name"><xsl:value-of select="normalize-space(substring-before(.,'='))"/></xsl:attribute>
                <xsl:attribute name="value"><xsl:value-of select="substring-after(.,'=')"/></xsl:attribute>
            </parameter>            
        </xsl:if>
    </xsl:for-each>
</xsl:template>

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

</xsl:stylesheet>


= Conclusion =