Re: [xsl] with-param looping problem...

Subject: Re: [xsl] with-param looping problem...
From: "James A. Robinson" <jim.robinson@xxxxxxxxxxxx>
Date: Mon, 09 Oct 2006 19:33:51 -0700
> But here's a question - I mentioned in an earlier post that the
> sample code I sent represented a subset of information from a
> project file. Most of the processing seems to occur at the
> //Assignemnt node.  What if I have to apply additonal filters at the
> //Task or //Resource levels? Suppose that there is an additional
> element in the //Task level that identifies 'ActiveProjects'? That
> was why I thought a <for each> on the //Task node was the way to go.

You could still use that technique, basically you just isolate the
Task (or Resource) you want to deal with and use it to apply-templates
against the Assignment with the given TaskUID (or ResourceUID):

  <xsl:template match="Task">
    <xsl:apply-templates select="/Project/Assignments/Assignment[TaskUID = current()/UID]"/>
  </xsl:template>

  <xsl:template match="Resource">
    <xsl:apply-templates select="/Project/Assignments/Assignment[ResourceUID = current()/UID]"/>
  </xsl:template>

A modified version of what I sent before, where I drive everything based
off a $mode parameter for ActiveProject tasks is below.  You can see
that I'm performing a simple filter based on ActiveProject, but there
is no reason you can't get more complicated within that block of logic
(selecting Resource or Task as appropriate):

  <?xml version="1.0" encoding="UTF-8"?>
  <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; version="2.0">

    <xsl:output indent="yes" />

    <!--
      parameter: mode
      values: active, inactive, all
    -->
    <xsl:param name="mode" select="'active'" />

    <!--
      Emit table detailing Tasks according to $mode.
    -->
    <xsl:template match="/">
      <xsl:choose>
        <xsl:when test="$mode = 'active'">
          <table>
            <xsl:apply-templates select="/Project/Tasks/Task[ActiveProject = 'Yes']" />
          </table>
        </xsl:when>
        <xsl:when test="$mode = 'inactive'">
          <table>
            <xsl:apply-templates select="/Project/Tasks/Task[ActiveProject = 'No']" />
          </table>
        </xsl:when>
        <xsl:when test="$mode = 'all'">
          <table>
            <xsl:apply-templates select="/Project/Tasks/Task" />
          </table>
        </xsl:when>
        <xsl:otherwise>
          <xsl:message terminate="yes">
            <xsl:text>Invalid Mode: '</xsl:text>
            <xsl:value-of select="$mode" />
            <xsl:text>' allowed values are 'active', 'inactive', and 'all'.</xsl:text>
          </xsl:message>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:template>

    <xsl:template match="Task">
      <xsl:apply-templates select="/Project/Assignments/Assignment[TaskUID = current()/UID]"/>
    </xsl:template>

    <xsl:template match="Resource">
      <xsl:apply-templates select="/Project/Assignments/Assignment[ResourceUID = current()/UID]"/>
    </xsl:template>


    <xsl:template match="Assignments/Assignment">
      <tr>
        <xsl:apply-templates select="TaskUID"/>
        <xsl:apply-templates select="UID"/>
        <xsl:apply-templates select="ResourceUID"/>
      </tr>
    </xsl:template>

    <xsl:template match="Assignment/UID">
      <td><xsl:value-of select="string(.)"/></td>
    </xsl:template>

    <xsl:template match="Assignment/TaskUID">
      <td><xsl:value-of select="/Project/Tasks/Task[UID = string(current())]/Name"/></td>
    </xsl:template>

    <xsl:template match="Assignment/ResourceUID">
      <td><xsl:value-of select="/Project/Resources/Resource[UID = string(current())]/Name"/></td>
    </xsl:template>

  </xsl:stylesheet>

However, I think I understand that you might be approaching this more
as a database query type of operation -- and you'd prefer a more
direct sort of 'lookup' operation?

In that case, recall that you can nest calls to key(), assuming
certain things about the data.  For example, I'm assuming that UID
means Unique Identifier, and that only one Task has a given //Task/UID
value, and the same for Resource and Assignment.  I'm also assuming
all Task entries have an Assignment:

  <?xml version="1.0" encoding="UTF-8"?>
  <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; version="2.0">

    <xsl:key name="Resource" match="Resource" use="UID" />
    <xsl:key name="AssignmentForTask" match="Assignment" use="TaskUID" />

    <xsl:output indent="yes" />

    <!--
      parameter: mode
      values: active, inactive, all
    -->
    <xsl:param name="mode" select="'active'" />

    <!--
      Emit table detailing Tasks according to $mode.
    -->
    <xsl:template match="/">
      <xsl:choose>
        <xsl:when test="$mode = 'active'">
          <table>
            <xsl:apply-templates select="/Project/Tasks/Task[ActiveProject = 'Yes']" mode="TaskDisplay" />
          </table>
        </xsl:when>
        <xsl:when test="$mode = 'inactive'">
          <table>
            <xsl:apply-templates select="/Project/Tasks/Task[ActiveProject = 'No']" mode="TaskDisplay" />
          </table>
        </xsl:when>
        <xsl:when test="$mode = 'all'">
          <table>
            <xsl:apply-templates select="/Project/Tasks/Task" mode="TaskDisplay" />
          </table>
        </xsl:when>
        <xsl:otherwise>
          <xsl:message terminate="yes">
            <xsl:text>Invalid Mode: '</xsl:text>
            <xsl:value-of select="$mode" />
            <xsl:text>' allowed values are 'active', 'inactive', and 'all'.</xsl:text>
          </xsl:message>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:template>

    <!--
      Task driven display of Project data:
        Emits a table row containing the Task Name,
        Assignment UID, and Resource Name
    -->
    <xsl:template match="Task" mode="TaskDisplay">
      <tr>
        <xsl:apply-templates select="Name" mode="#current" />
        <xsl:apply-templates select="key('AssignmentForTask', UID)" mode="#current" />
        <xsl:apply-templates select="key('Resource', key('AssignmentForTask', UID)/ResourceUID)" mode="#current" />
      </tr>
    </xsl:template>
    <xsl:template match="Task/Name" mode="TaskDisplay">
      <td>
        <xsl:value-of select="." />
      </td>
    </xsl:template>
    <xsl:template match="Assignment" mode="TaskDisplay">
      <td>
        <xsl:value-of select="UID" />
      </td>
    </xsl:template>
    <xsl:template match="Resource" mode="TaskDisplay">
      <td>
        <xsl:value-of select="Name" />
      </td>
    </xsl:template>

  </xsl:stylesheet>

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
James A. Robinson                       jim.robinson@xxxxxxxxxxxx
Stanford University HighWire Press      http://highwire.stanford.edu/
+1 650 7237294 (Work)                   +1 650 7259335 (Fax)

Current Thread