Re: [xsl] Run-time polymorphism in XSL 1.0

Subject: Re: [xsl] Run-time polymorphism in XSL 1.0
From: "Andrey Basko" <andrey_basko@xxxxxxxxxxxxxxxx>
Date: Mon, 21 Mar 2005 00:31:21 -0500
Hi Dimitre,

Yes, the approach you specified is very similar, but I still see some differences.

First of all, I don't use any extensions like msxsl:node-set() in my approach. And you didn't specify the mechanism of inheritance (in your example), that's why you could find my description a little-bit too-complicated. Also I used duplication in methods name and method attibutes for convenience purposes. It is possible to declare methods as follows: <Base:method name="Method1"/>, but in this case template handler would look like:
<xsl:template match="Base:*[@name='Method1']/>,
but I like more the proposed format:
<xsl:template match="Base:Method1"/>
And I still need attributes to do set difference operation between base class methods and child class methods.


I just reproduced the behaviour of virtual methods from usual OOP languages like C++, C#, Java, but this approach still allow everybody to use the full power of XSL or HOF that you invented.
Actually, when we speak about HOF we speak about how to pass a reference to a function to another function as a parameter (or how to return a reference to a function). Here we could speak about passing references to class methods, like pointers to virtual functions in C++. It could be done using proposed approach by passing the following parameters:
<xsl:param name="someClassThis" select="{something}"/> <!-- pointer to XML data -->
<xsl:param name="someClassVtable" select="$someClass:vtable"/> <!-- pointer to virtual table -->
<xsl:param name="someClassMethodName" select="'MethodName'"/> <!-- method name -->
These parameters will pass a reference to someClass:MethodName method.


Best Regards,
Andrey

----- Original Message ----- From: "Dimitre Novatchev" <dnovatchev@xxxxxxxxx>
To: <xsl-list@xxxxxxxxxxxxxxxxxxxxxx>
Sent: Sunday, March 20, 2005 9:56 PM
Subject: Re: [xsl] Run-time polymorphism in XSL 1.0



Hi Andrey,

Yes, this is one way to simulate virtual functions. The description
seems a little-bit too-complicated.

This approach was first described (in a more simple way -- just by an
example) at:

http://www.biglist.com/lists/xsl-list/archives/200111/msg01100.html

and later in:


http://www.mulberrytech.com/Extreme/Proceedings/xslfo-pdf/2003/Novatchev01/EML2003Novatchev01.pdf



My personal observations indicate that such type of run-time polymorphism is much-too clumsy and to the best of my knowledge has not been used in a system that exploits the much more powerful, natural and convenient mechanism of using Higher Order Functions (HOFs).

Another stumbling block is that no type-checking can be provided in
both XSLT/XPath 1.0 *and* 2.0.

It is extremely awkward not to be able to define the necessary types
inline in a stylesheet. One has to define them separately in XSD.

The C-Omega language gives the ability to conveniently define such
types inline and in this respect provides a better programming
environment than XSLT 2.0.

Cheers,
Dimitre Novatchev.

On Sun, 20 Mar 2005 18:51:21 -0500, Andrey Basko
<andrey_basko@xxxxxxxxxxxxxxxx> wrote:
Hi, All!

Some time ago I tried to find reliable approach how to implement run-time
polymorphism in XSL 1.0. Initially I used inbuilt polymorphism-like template
overriding mechanism based on import precedence. However I encountered the
issues described in: ("Reliance on import precedence considered dangerous"
http://sources.redhat.com/ml/xsl-list/2001-02/msg00996.html, and
http://sources.redhat.com/ml/xsl-list/2001-02/msg01003.html).


In XSL forums I found several messages that mentioned how to implement
polymorphism in XSL 1.0 based on generic templates proposed by Dmity
Novatchev
(http://lists.fourthought.com/pipermail/exslt/2001-May/000169.html).

Eventually I came up with some approach that I would like to share with the
XSL community. The idea how to implement run-time polymorphism in XSL is
similar to approach used in generic templates:


1. Declare special customized data structures (under non-xsl namespace,
embedded in the stylesheet) which define:
   a. Virtual methods in logically defined class.
   b. Virtual methods table variable by inheriting methods from virtual
methods table of base "class".

2. Pass reference to virtual methods table to all virtual methods as a
parameter.

Below I describe several "how to" steps in order to explain how to declare
two classes: Base "class" and Child "class" that inherits from Base "class".


1. How to declare Base class.

a. Declare Base class namespace:

<xsl:stylesheet [...] xmlns:Base="Base">

b. Declare Base class methods and virtual table:

<Base:class>
  <Base:Method1 method="Method1"/>
  <Base:Method2 method="Method2"/>
</ Base:class>

<xsl:variable name="Base:class" select="document('')// Base:class"/>
<xsl:variable name="Base:vtable" select="$Base:class/*"/>

The variable "$Base:vtable" is a virtual table for Base class.

2. How to declare Base class method handlers.

<xsl:template match="Base:Method1">
  <xsl:param name="this"/>
  <xsl:param name="vtable"/>
  <!-- code is here -->
</xsl:template>

Each method should declare "vtable" parameter. The "this" parameter is
supposed to be used as a node reference to real XML data.

3. How to declare Child class

a. Declare Base and Child class namespaces:

<xsl:stylesheet [...] xmlns:Child="Child" xmlns:Base="Base">

b. Use <xsl:include> if necessary:

<xsl:include href="Base.xsl"/>

c. Declare Child class methods and inherit virtual methods from Base class:

<Child:class>
  <Child:Method1 method="Method1"/>
  <Child:NewMethod3 method="NewMethod3"/>
</Child:class>

<xsl:variable name="Child:class" select="document('')//Child:class"/>
<xsl:variable name="Child:BaseMethods"
select="$Base:vtable[not(@method=$Child:class/*/@method)]"/>

<xsl:variable name="Child:vtable" select="$Child:class/* |
$Child:BaseMethods"/>

Variable "$Child:BaseMethods" contains only those methods that are declared
in the Base class but not declared in the Child class.


So, each class declares its own virtual table that is accessible by
"${ClassNamespace}:vtable" variable. In this example virtual tables are:
"$Base:vtable" and "$Child:vtable".

4. How to make virtual method call:

<xsl:template match="Base:Method1">
  <xsl:param name="this"/>
  <xsl:param name="vtable"/>

  <xsl:apply-templates select="$vtable[local-name()='Method2']">
     <xsl:with-param name="this" select="$this"/>
     <xsl:with-param name="vtable" select="$vtable"/>
     <!-- Other Method2 parameters -->
  </xsl:apply-templates>
</xsl:template>

5. How to call base class methods from child classes:

<xsl:template match="Child:Method1"> <!-- declaration of Child:Method1
handler -->
  <xsl:param name="this"/>
  <xsl:param name="vtable"/>
  <doSomethingNew>
     <xsl:apply-templates select="$Base:vtable[local-name()='Method1']">
        <xsl:with-param name="this" select="$this"/>
        <xsl:with-param name="vtable" select="$vtable"/>
     </xsl:apply-templates>
  </doSomethingNew>
</xsl:template>

It means that in order to call base class methods you need to select method
from concrete class virtual table. But it is still necessary to pass source
$vtable parameter to it.


6. How to define special handler for abstract methods:

It is easy to force overriding of all abstract methods by declaring the
following template in corresponding class (in this case it is Base class):


<xsl:template match="*[namespace-uri()='Base']" priority="-1">
  <xsl:message terminate="yes">
     Abstract method "Base:<xsl:value-of select="local-name()"/>" was
called
  </xsl:message>
</xsl:template>

Hope somebody will enjoy this approach while developing with XSL.

Best Regards,
Andrey Basko

Current Thread