0

我一直试图弄清楚为什么我的变量分配总和不起作用,而且我的表输出在整个表中只重复第一个元素。我试图让这段代码做的是让每个学生的学生 ID 打印在第一列中,该 ID 的学生姓名在第二列中,然后分配一个变量来保存学生在他们的 3 次评估中的总分已完成在第三栏中打印他们的总分,然后根据他们的总分分配 HD、D、C、P 或 F,例如 HD 是 85+,D 是 75+,但不高于 84。等.

有人可以告诉我哪里出错了吗?我对 XML/XSL 还是新手,所以欢迎批评。

等级.xsl

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">

    <xsl:variable name="StudentAmount" select="count(document('AssessmentItems.xml')/assessmentList/unit/studentList/student)"/>
    <xsl:variable name="totalmark" select="sum(document('AssessmentItems.xml')/assessmentList/unit/*
    [//assessmentList/unit/assessmentItems/assessment/@studId = //assessmentList/unit/studentList/student/@sid])"/>

  <html>
  <body>
    <h2>Grade Report for <xsl:value-of select="assessmentList/unit/@unitId"/> - <xsl:value-of select="assessmentList/unit/unitName"/></h2>
    <p>Number of students in this unit: <xsl:value-of select="$StudentAmount"/></p>

    <table border="1">
      <tr>
        <th>ID</th>
        <th>Name</th>
        <th>Total Mark</th>
        <th>Grade</th>
      </tr>
      <xsl:for-each select="assessmentList/unit/studentList/student">
      <tr>
        <td><xsl:value-of select="document('AssessmentItems.xml')/assessmentList/unit/studentList/student/@sid"/></td>
        <td><xsl:value-of select="document('AssessmentItems.xml')/assessmentList/unit/studentList/student"/></td>
        <td><xsl:value-of select="document('AssessmentItems.xml')/assessmentList/unit/assessmentItems/assessment/mark"/></td>

        <xsl:choose>
        <xsl:when test="$totalmark &gt; 85">
        <td color="blue">HD</td>
        </xsl:when>

        <xsl:when test="$totalmark &gt; 75">
        <td color="black">D</td>
        </xsl:when>

        <xsl:when test="$totalmark &gt; 65">
        <td color="black">C</td>
        </xsl:when>

        <xsl:when test="$totalmark &gt; 50">
        <td color="black">P</td>
        </xsl:when>

        <xsl:otherwise>
        <td color="red">F</td>
        </xsl:otherwise>
        </xsl:choose>

      </tr>
      </xsl:for-each>
    </table>

    </body>
  </html>
</xsl:template>
</xsl:stylesheet>

这是文件 AssessmentItems.xml

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="grade.xsl"?>
<assessmentList>
    <unit unitId="3311">
        <unitName>Learn To Read</unitName>
        <studentList>
            <student sid="1001">Lisa Simpson</student>
            <student sid="1002">Barney Rubble</student>
            <student sid="1003">Donald Duck</student>
        </studentList>
        <assessmentItems>
            <assessment name="Assignment 1" weight="20">
                <mark studId="1001">12</mark>
                <mark studId="1002">18</mark>
                <mark studId="1003">9</mark>
            </assessment>
            <assessment name="Assignment 2" weight="25">
                <mark studId="1001">23</mark>
                <mark studId="1002">14</mark>
                <mark studId="1003">12.5</mark>
            </assessment>
            <assessment name="Quiz" weight="15">
                <mark studId="1001">13</mark>
                <mark studId="1002">9</mark>
                <mark studId="1003">6</mark>
            </assessment>
            <assessment name="Final Exam" weight="40">
                <mark studId="1001">38</mark>
                <mark studId="1002">21</mark>
                <mark studId="1003">20.5</mark>
            </assessment>
        </assessmentItems>
    </unit>
</assessmentList>
4

2 回答 2

0

A very quick glance at your code reveals that the predicate

[//assessmentList/unit/assessmentItems/assessment/@studId = //assessmentList/unit/studentList/student/@sid]

is obviously wrong, because it has the same value (either true or false) for every element in your source document.

Correcting it requires more study of the problem than I have time for. But you seem to have fallen victim to the "if it doesn't work then put '//' at the front" fallacy.

于 2012-05-10T11:31:16.650 回答
0

首先,因为您只处理单个 XML 文档,所以根本不需要对 document('AssessmentItems.xml') 的常量引用。所以,例如

<xsl:value-of 
   select="document('AssessmentItems.xml')/assessmentList/unit/studentList/student/@sid"/>

可以只替换

<xsl:value-of select="/assessmentList/unit/studentList/student/@sid"/>

这就引出了第二个问题。上面的 xpath 是相对于 XML 的文档元素的,它将返回它找到的第一个学生的@sid,而不是你当前所在的学生的@sid。您可以在您的情况下简单地执行此操作

<xsl:value-of select="@sid"/>

另一个问题是您在 XSLT 的顶部定义变量totalmarks,而实际上它应该在您的xsl:for-each范围内定义,以便它特定于当前学生

<xsl:variable name="totalmark" select="sum(../../assessmentItems/assessment/mark[@studId = current()/@sid])" />

实际上,最好在这里使用一个键来查找结果

<xsl:key name="marks" match="mark" use="@studId" />

并获得学生的总成绩......

 <xsl:variable name="totalmark" select="sum(key('marks', @sid))" />

最后一条评论,虽然不是问题,但通常最好使用xsl:apply-templates而不是xsl:for-each,因为这样可以避免过多的缩进,并允许更好的代码重用。

尝试以下 XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:key name="marks" match="mark" use="@studId"/>

   <xsl:template match="/">
      <xsl:variable name="StudentAmount" select="count(/assessmentList/unit/studentList/student)"/>
      <html>
         <body>
            <h2>Grade Report for 
               <xsl:value-of select="assessmentList/unit/@unitId"/>- 
               <xsl:value-of select="assessmentList/unit/unitName"/>
            </h2>
            <p>Number of students in this unit: 
               <xsl:value-of select="$StudentAmount"/></p>
            <table border="1">
               <tr>
                  <th>ID</th>
                  <th>Name</th>
                  <th>Total Mark</th>
                  <th>Grade</th>
               </tr>
               <xsl:apply-templates select="assessmentList/unit/studentList/student"/>
            </table>
         </body>
      </html>
   </xsl:template>

   <xsl:template match="student">
      <xsl:variable name="totalmark" select="sum(key('marks', @sid))"/>
      <tr>
         <td>
            <xsl:value-of select="@sid"/>
         </td>
         <td>
            <xsl:value-of select="."/>
         </td>
         <td>
            <xsl:value-of select="$totalmark"/>
         </td>
         <xsl:choose>
            <xsl:when test="$totalmark &gt; 85">
               <td color="blue">HD</td>
            </xsl:when>
            <xsl:when test="$totalmark &gt; 75">
               <td color="black">D</td>
            </xsl:when>
            <xsl:when test="$totalmark &gt; 65">
               <td color="black">C</td>
            </xsl:when>
            <xsl:when test="$totalmark &gt; 50">
               <td color="black">P</td>
            </xsl:when>
            <xsl:otherwise>
               <td color="red">F</td>
            </xsl:otherwise>
         </xsl:choose>
      </tr>
   </xsl:template>
</xsl:stylesheet>

应用于您的 XML 时,将输出以下 HTML

<html>
   <body>
      <h2>Grade Report for 3311- Learn To Read</h2>
      <p>Number of students in this unit: 3</p>
      <table border="1">
         <tr>
            <th>ID</th>
            <th>Name</th>
            <th>Total Mark</th>
            <th>Grade</th>
         </tr>
         <tr>
            <td>1001</td>
            <td>Lisa Simpson</td>
            <td>86</td>
            <td color="blue">HD</td>
         </tr>
         <tr>
            <td>1002</td>
            <td>Barney Rubble</td>
            <td>62</td>
            <td color="black">P</td>
         </tr>
         <tr>
            <td>1003</td>
            <td>Donald Duck</td>
            <td>48</td>
            <td color="red">F</td>
         </tr>
      </table>
   </body>
</html>

请注意,这假定您的 XML 中只有一个单元元素。如果您的实际 XML 有多个单元,并且您希望每个单元都有一个单独的表,那么这不是问题,您只需要确保单元 id 是xsl:key的一部分,这样您就可以查找给定的结果给定单元的学生。

于 2012-05-10T09:58:22.603 回答