RE: [xsl] Can't get predicates working.

Subject: RE: [xsl] Can't get predicates working.
From: "Aron Bock" <aronbock@xxxxxxxxxxx>
Date: Sat, 07 May 2005 22:31:22 +0000
Marco,

On this input (your input corrected for markup):


<company> <division DID="XXX"> <projects> <project PID='XYZ'> (Project ID) <PNAME>Some Name</PNAME> (Project Name) <BUDGET>111</BUDGET> <assigns> <assign refEID='XXX000'> <HOURS>12</HOURS> </assign> <assign refEID='XXX001'> <HOURS>78</HOURS> </assign> </assigns> </project> <project PID='XY1'> <PNAME>Some OtherName</PNAME> <BUDGET>112</BUDGET> <assigns> <assign refEID='XXX000'> <HOURS>34</HOURS> </assign> <assign refEID='XXX002'> <HOURS>1234</HOURS> </assign> </assigns> </project> Etc.. </projects> <employees> <employee EID='XXX000'> <ENAME>Joe Blow</ENAME> <OFFICE>1204</OFFICE> <BIRTHDATE>1924-08-01</BIRTHDATE> </employee> <employee EID='XXX001'> <ENAME>Joe Smith</ENAME> <OFFICE>1203</OFFICE> <BIRTHDATE>1930-08-01</BIRTHDATE> </employee> <employee EID='XXX002'> <ENAME>Joe Jerry</ENAME> <OFFICE>0003</OFFICE> <BIRTHDATE>1930-08-01</BIRTHDATE> </employee> </employees> </division> </company>

This XSL:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; version="1.0">
<xsl:output method="text"/>


<xsl:key match="employee" name="employee-by-refEID" use="@EID"/>

   <xsl:template match="/">
       <xsl:apply-templates select="company/division"/>
   </xsl:template>

<xsl:template match="division">
<xsl:text>Division Name = </xsl:text><xsl:value-of select="@DID"/><xsl:text>&#xa;</xsl:text>
<xsl:apply-templates select="projects/project"/>
</xsl:template>


   <xsl:template match="project">
       <xsl:text>PID = </xsl:text><xsl:value-of select="@PID"/>
       <xsl:text>, PNAME = </xsl:text><xsl:value-of select="PNAME"/>
       <xsl:text>, BUDGET = </xsl:text><xsl:value-of select="BUDGET"/>
       <xsl:text>&#xa;</xsl:text>

       <!-- list employees using key() -->
       <xsl:apply-templates select="assigns/assign" mode="use-key"/>
       <xsl:text>&#xa;</xsl:text>

       <!-- list employees using relative path -->
       <xsl:apply-templates select="assigns/assign" mode="relative-path"/>

       <xsl:text>&#xa;</xsl:text>
   </xsl:template>

<xsl:template match="assign" mode="use-key">
<xsl:text>EID = </xsl:text><xsl:value-of select="@refEID"/>
<xsl:text>, ENAME = </xsl:text><xsl:value-of select="key('employee-by-refEID', @refEID)/ENAME"/>
<xsl:text>, OFFICE = </xsl:text><xsl:value-of select="key('employee-by-refEID', @refEID)/OFFICE"/>
<xsl:text>, HOURS = </xsl:text><xsl:value-of select="HOURS"/>
<xsl:text>&#xa;</xsl:text>
</xsl:template>


<xsl:template match="assign" mode="relative-path">
<xsl:variable name="refeid" select="@refEID"/>
<xsl:variable name="emp" select="/company/division/employees/employee[@EID = current()/@refEID]"/>


<xsl:text>EID = </xsl:text><xsl:value-of select="@refEID"/>
<xsl:text>, ENAME = </xsl:text><xsl:value-of select="/company/division/employees/employee[@EID = current()/@refEID]/ENAME"/>
<xsl:text>, OFFICE = </xsl:text><xsl:value-of select="../../../../employees/employee[@EID = @refeid]/OFFICE"/>
<xsl:text>, BIRTHDATE = </xsl:text><xsl:value-of select="$emp/BIRTHDATE"/>
<xsl:text>, HOURS = </xsl:text><xsl:value-of select="HOURS"/>
<xsl:text>&#xa;</xsl:text>
</xsl:template>
</xsl:stylesheet>


Produces this output:

Division Name = XXX
PID = XYZ, PNAME = Some Name, BUDGET = 111
EID = XXX000, ENAME = Joe Blow, OFFICE = 1204, HOURS = 12
EID = XXX001, ENAME = Joe Smith, OFFICE = 1203, HOURS = 78

EID = XXX000, ENAME = Joe Blow, OFFICE = , BIRTHDATE = 1924-08-01, HOURS = 12
EID = XXX001, ENAME = Joe Smith, OFFICE = , BIRTHDATE = 1930-08-01, HOURS = 78


PID = XY1, PNAME = Some OtherName, BUDGET = 112
EID = XXX000, ENAME = Joe Blow, OFFICE = 1204, HOURS = 34
EID = XXX002, ENAME = Joe Jerry, OFFICE = 0003, HOURS = 1234

EID = XXX000, ENAME = Joe Blow, OFFICE = , BIRTHDATE = 1924-08-01, HOURS = 34
EID = XXX002, ENAME = Joe Jerry, OFFICE = , BIRTHDATE = 1930-08-01, HOURS = 1234



The employee-list is repeated per project for pedagogical purposes only.


If you want text output with aligned columns, search the net for templates that pad and justify text. Alternatively you could generate HTML output and use tables.

I assume your real issue was how, once you were at a node, to get related information from another node. Thus the stylesheet above shows how to do it using keys, using an absolute path and matching on a common attribute, and using a relative path and matching on a common attribute. Along the way it also shows the use of modes, the current() function, and avoiding the current() function by using a previously-initialized variable.

keys() are useful when you need to locate something repeatedly and fast; I believe internally this is represented as a hash structure, so what you gain in speed you may lose in memory. The usual space/time tradeoff.

When you need to access something repeatedly, but only in one place, it's useful to create a local variable, as we do with $emp. That gives you to the advantage of doing the full lookup just once and subsequent lookups locally, without the reference staying around until transform-end (as would be the case with keys).

BTW, I suppose more and more of your "company" XML is slowly being dribbled in as you encounter new issues in its transformation. Your taking the time to cull out only the portions of interest is appreciated. If you would, however, it would be huge if the subjectline reflected the issue at hand--for instance, how to traverse to or display information from "related" nodes. Often, in formulating the issue you may have some insight into its solutions!

:-)

Regards,

--A

_________________________________________________________________
Dont just search. Find. Check out the new MSN Search! http://search.msn.click-url.com/go/onm00200636ave/direct/01/


Current Thread