Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Transform help 1

Status
Not open for further replies.

Crundy

Programmer
Jul 20, 2001
305
GB
Hi all,
Can someone give me a hand with this? I have an XML document which contains results of a questionnaire. The questions are listed at the top of the document and each user's response(s) are listed below. Users may not have answered all the questions, and if they have not answered a question then a node for the response does not appear in the XML. The questions have odd numbering and are in a completely random order, but are asked in order of display in the XML. For example:

Code:
<?xml version="1.0" encoding="utf-8"?>
<QuestionGrid>
  <Questions>
    <Question QuestionId="51" QuestionText="Favorite Music" />
    <Question QuestionId="52" QuestionText="Favorite Place" />
    <Question QuestionId="2" QuestionText="Favorite Food" />
  </Questions>
  <Response ResponseId="8621" EmployeeName="Fred Bloggs" DepartmentName="training">
    <Answer QuestionId="51" Answer="The Killers" />
  </Response>
  <Response ResponseId="8622" EmployeeName="A Nonymouse" DepartmentName="IT">
    <Answer QuestionId="51" Answer="Kings of Leon" />
    <Answer QuestionId="52" Answer="Florida" />
    <Answer QuestionId="2" Answer="Hamburgers" />
  </Response>
  <Response ResponseId="8623" EmployeeName="Dan Tman" DepartmentName="training">
    <Answer QuestionId="2" Answer="Sushi" />
  </Response>
</QuestionGrid>

I need to display an HTML table of all the results like this:

Code:
Name         Department     Favorite Music     Favorite Place     Favorite Food
Fred Bloggs  training       The Killers
A Nonymouse  IT             Kings of Leon      Florida            Hamburgers
Dan Tman     training                                             Sushi

I got as far as:

Code:
    <xsl:output method="html" indent="yes"/>
    <xsl:template match="/">
      <table border="1" class="defaultstyle">
        <tr>
          <th style="writing-mode: tb-rl; text-align:right;">Employee</th>
          <th style="writing-mode: tb-rl; text-align:right;">Department</th>
          <xsl:for-each select="QuestionGrid/Questions/Question">
            <th style="writing-mode: tb-rl; text-align:right;">
              <xsl:value-of select="@QuestionText"/>
            </th>
          </xsl:for-each>
        </tr>
        <xsl:for-each select="QuestionGrid/Response">
          <tr>
            <td>
              <xsl:value-of select="@EmployeeName"/>
            </td>
            <td>
              <xsl:value-of select="@DepartmentName"/>
            </td>
            <xsl:for-each select="QuestionGrid/Questions/Question">
              <xsl:apply-templates select="Answer">
                <xsl:with-param name="ResponseId" select="@ResponseId" />
              </xsl:apply-templates>
            </xsl:for-each>
          </tr>
        </xsl:for-each>
      </table>
    </xsl:template>
  <xsl:template match="Answer">
    <xsl:param name="ResponseId"/>
    <td>
      <xsl:value-of select="/QuestionGrid/Response[@ResponseId=$ResponseId]/Answer[@QuestionId=@QuestionId]/@Answer"/>
    </td>
  </xsl:template>

Which doesn't work at all. Can anyone help?

C:\DOS:>
C:\DOS:>RUN
RUN DOS RUN!!
 
[1] You can start with a less sophisticated but more akin to procedural. If you don't get the idea at first glance, it is your job to study it to some extent to understand what's it is all about.
[tt]
<xsl:template match="/">
<table border="1" class="defaultstyle">
<xsl:apply-templates select="QuestionGrid" />
</table>
</xsl:template>
<xsl:template match="QuestionGrid">
<xsl:apply-templates select="*" />
</xsl:template>
<xsl:template match="Questions">
<tr>
<th style="writing-mode: tb-rl; text-align:right;">Employee</th>
<th style="writing-mode: tb-rl; text-align:right;">Department</th>
<xsl:for-each select="Question">
<!--
<xsl:sort select="@QuestionId" order="ascending" />
-->
<th style="writing-mode: tb-rl; text-align:right;">
<xsl:value-of select="@QuestionText"/>
</th>
</xsl:for-each>
</tr>
</xsl:template>
<xsl:template match="Response">
<xsl:variable name="ref" select="." />
<tr>
<td>
<xsl:value-of select="@EmployeeName"/>
</td>
<td>
<xsl:value-of select="@DepartmentName"/>
</td>
<xsl:for-each select="parent::*/Questions[1]/Question">
<!--
<xsl:sort select="@QuestionId" order="ascending" />
-->
<td>
<xsl:choose>
<xsl:when test="$ref/child::Answer[@QuestionId=current()/@QuestionId]">
<xsl:value-of select="$ref/child::Answer[@QuestionId=current()/@QuestionId][1]/@Answer"/>
</xsl:when>
<xsl:eek:therwise>
<xsl:value-of select="'&#xa0;'" />
</xsl:eek:therwise>
</xsl:choose>
</td>
</xsl:for-each>
</tr>
</xsl:template>
[/tt]
[2] After that, you may google something more with keyword "xsl:key" for a more sophisticated approach. For large question-set, it would be more efficient. For small, the contrary.
 
That's excellent. Thank you.
Have a star.

C:\DOS:>
C:\DOS:>RUN
RUN DOS RUN!!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top