This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Dynamic modes: A generic solution


Hello, friends.

Suppose that we want every node with, say, a specific
namespace "x" be transformed in its own way, but with
another node as a context node (uniformly determined
by the node under transformation).

Here is a possible solution:

  <xsl:template match="x:nameX">
    <xsl:apply-templates select="new-context()"
                         mode="x:nameX"/>
  </xsl:template>

  <xsl:template match="context" mode="x:nameX">
    nameX-specific code
  </xsl:template>

where new-context() is an expression that,
according to the current node, returns a node list
with a single node whose name is "context".

This works, but, proceeding in this way, we have to
present an explicit extra template matched by x:nameX
for each node of type x:*.

If we might use AVTs as mode's values, we would write
a single template like this:

  <xsl:template match="x:*">
    <xsl:apply-templates select="new-context(.)"
                         mode="{name()}"/>
  </xsl:template>

Alas, as is known, AVTs are not allowed there.

The problem is similar to that solved by generic templates.
So, let's consider a solution involving a "choose" operator:

  <xsl:template match="x:*">
    <xsl:for-each select="new-context(.)">
      <xsl:choose>
        <xsl:when test="local-name()='name1'">
          name1-specific code
        </xsl:when>
        <xsl:when test="local-name()='name2'">
          name2-specific code
        </xsl:when>
        ...
      </xsl:choose>
    </xsl:for-each>
  </xsl:template>

This is a "generic" analog:

  <xsl:template match="x:*">
    <xsl:call-template name="transform">
      <xsl:with-param name="mode" select=
        "document('')/*/y:*[local-name()=local-name(current())]"/>
    </xsl:call-template>
  </xsl:template>

  <xsl:template name="transform">
    <xsl:param name="mode"/>
    <xsl:apply-templates select="$mode">
      <xsl:with-param name="context" select="new-context()"/>
    </xsl:apply-templates>
  </xsl:template>

Then, for each nameX, we can write the following:

  <y:nameX/>
  <xsl:template match="y:nameX">
    <xsl:param name="context"/>
    <xsl:for-each select="$context">
      nameX-specific code
    </xsl:for-each>
  </xsl:template>

Not so bad. The only sad thing is that we have to insert
those xsl:param and xsl:for-each in each template.
I wonder if there exists a more adequate solution.
Any ideas?

-- 
Alexander E. Gutman

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]