xsl键与xpath谓词匹配

时间:2016-03-25 07:10:37

标签: xml xslt xpath

我正在学习XML / XSLT / XPATH并且有一些特定的方法,但希望通过删除重复代码来提高效率。

XML示例

<student>
     <scores>
          <score scoreID="1"  weight="10" mandatory="false">7</score>
          <score scoreID="2"  weight="10" mandatory="false">9</score>
          <score scoreID="3"  weight="30" mandatory="true">13</score>
     </scores>
</student>

<student>
     <scores>
          <score scoreID="1"  weight="10" mandatory="false">8</score>
          <score scoreID="2"  weight="10" mandatory="false">4</score>
          <score scoreID="3"  weight="30" mandatory="true">25</score>
     </scores>
</student>

所以基本上我有一些XSL检查

  • 如果得分总和大于25(即总重量的一半)
  • 如果强制元素为真,则将分数除以权重。
  • 如果结果大于0.5;打印适当的结果

这是通过以下表达式完成的

XSL

<xsl:when test="sum(scores/score) &gt; 25 and scores/score[@mandatory='True' and .div @weight &lt; 0.5]">

除了我有很多学生和很多分数外,这一切都很好,因为我在每个分数下都写了重量和强制值,所以效率并不高。

我想要做的是声明另一个具有权重和强制属性的结构,然后用键将它们引用到每个分数。

所以我的XML更喜欢这样(基本上没有每个分数下的权重和强制属性)

<quizDetails>
      <quiz quizID="1" weight="10" mandatory="false" />
      <quiz quizID="2" weight="10" mandatory="false" />  
      <quiz quizID="3" weight="30" mandatory="true" />
</quizDetails>

<student>
     <scores>
          <score scoreID="1">7</score>
          <score scoreID="2">9</score>
          <score scoreID="3">13</score>
     </scores>
</student>

<student>
     <scores>
          <score scoreID="1">8</score>
          <score scoreID="2">4</score>
          <score scoreID="3">25</score>
     </scores>
</student>

以下是我尝试这样做的

定义键

<xsl:key name ="quizKey" match="quizDetails" use="@quizID" />
<xsl:key name ="weightKey" match="quizDetails" use="@weight" />
<xsl:key name ="mandatoryKey" match="quizDetails" use="@mandatory" />
<xsl:key name ="scoreKey" match="scores" use="@scoreID" />

条件测试

<xsl:when test="sum(scores/score) &gt; 25 and (key('quizKey', '@quizID') = key('scoreKey', '@scoreID')) and (key('mandatoryKey', 'true') .div (key('weightKey', '@weight') &lt0.5;">

条件测试相当有点

  • 我尝试删除属性
  • 周围的单引号
  • 我尝试过像scoreKey = quizKey
  • 这样的比较
  • 我尝试通过一次添加一个条件来简化条件表达式
  • 我已阅读并重新阅读W3C XSLT2.0参考中关于xsl:key的部分

使用键功能基本上是我的主要问题。我想复制我以前的xml和xsl但没有重复代码的行为。

2 个答案:

答案 0 :(得分:1)

如果我理解正确,你只需要一把钥匙:

<xsl:key name="quiz" match="quiz" use="@quizID" />

然后你可以看到 - 从student的上下文 - 如果至少有一个分数是强制性的,那么通过测试:

key('quiz', scores/score/@scoreID)/@mandatory='true' 

恐怕我不明白其他测试应该做什么。看起来它需要单独应用于每个分数?但这不是你原来的测试所做的。

另请注意,XML区分大小写:'True'等于'true'。

加了:

为了更清晰,请考虑以下模板:

<xsl:template match="scores">
    <xsl:variable name="total-score" select="sum(score)" />
    <xsl:variable name="total-weight" select="sum(key('quiz', score/@scoreID)/@weight)" />
    <xsl:copy>
        <xsl:for-each select="score">
            <xsl:variable name="quiz" select="key('quiz', @scoreID)" />
            <xsl:if test="$total-score &gt; $total-weight div 2 and $quiz/@mandatory='true' and . div $quiz/@weight &gt; 0.5">
                <xsl:copy-of select="."/>
            </xsl:if>
        </xsl:for-each>
    </xsl:copy>
</xsl:template> 

当满足以下所有条件时,这将输出个人分数:

  1. 此学生的所有分数总和大于其总体重的一半;
  2. 相关测验是强制性的;
  3. 得分除以其重量大于0.5。

答案 1 :(得分:1)

我认为你这里只需要一个密钥来查找 delete from usernamepassword join faculty_admininfo on (usernamepassword.username = faculty_admininfo.email_address) where faculty_admininfo.employee_id IN ('SCM-021232'); 元素

quiz

要查找当前分数元素的<xsl:key name="quizKey" match="quiz" use="@quizID" /> 元素,使用密钥将是这样的

quiz

这意味着你的表达式需要如下所示:

key('quizKey', @scoreID)

你可以通过仅选择一个键中的强制性测验元素来实际改进。例如

<xsl:when test="sum(scores/score) &gt; 25 
                and scores/score[number(.) div key('quizKey', @scoreID)[@mandatory='true']/@weight &lt; 0.5]">

然后条件如下:

<xsl:key name="mandatoryKey" match="quiz[@mandatory='true']" use="@quizID" />