2013-01-02 42 views
2

我需要在一个XForms表单来计算一个简单的加权平均。我怎样才能以优雅的声明方式使用XPath和/或XQuery?如何计算XPath或XQuery中的加权平均值?

[EDITED]这是源XML文档:

<Examens> 
    <Examen> 
     <ExamenId>1</ExamenId> 
     <Coef>1</Coef> 
     <Notes> 
      <Note> 
       <EleveId>100</EleveId> 
       <Valeur>4</Valeur> 
      </Note> 
      <Note> 
       <EleveId>101</EleveId> 
       <Valeur>4.2</Valeur> 
      </Note> 
      <Note> 
       <EleveId>102</EleveId> 
       <Valeur>3.8</Valeur> 
      </Note> 
     </Notes> 
    </Examen> 
    <Examen> 
     <ExamenId>2</ExamenId> 
     <Coef>2</Coef> 
     <Notes> 
      <Note> 
       <EleveId>100</EleveId> 
       <Valeur>5</Valeur> 
      </Note> 
      <Note> 
       <EleveId>101</EleveId> 
       <Valeur/> 
      </Note> 
      <Note> 
       <EleveId>102</EleveId> 
       <Valeur>3.5</Valeur> 
      </Note> 
     </Notes> 
    </Examen> 
    <Examen> 
     <ExamenId>3</ExamenId> 
     <Coef>3</Coef> 
     <Notes> 
      <Note> 
       <EleveId>100</EleveId> 
       <Valeur>6</Valeur> 
      </Note> 
      <Note> 
       <EleveId>101</EleveId> 
       <Valeur>5.4</Valeur> 
      </Note> 
      <Note> 
       <EleveId>102</EleveId> 
       <Valeur>2</Valeur> 
      </Note> 
     </Notes> 
    </Examen> 
</Examens> 

以下片段被正确地显示所述值(= ./Valeur)和重(= ./../../Coef):

<xforms:repeat nodeset="$currentBranche//Note[EleveId=$currentEleveId]"> 
    <xforms:output ref="./Valeur"/> 
    <xforms:output ref="./../../Coef"/> 
</xforms:repeat> 

顺便说一句,我还需要排除Valeur为空字符串的节点。例如,在使用XPath avg()函数进行以下简单平均计算时,如果一个节点的内容是空字符串,则会出现错误(“无法将其转换为double”)。这是一个问题,因为节点存在(它是模型实例的一部分),当用户尚未输入值时,该值为空字符串。

<xforms:output ref="round(avg($currentBranche//Note[EleveId=$currentEleveId]/Valeur)*100) div 100"/> 

[EDITED]

正确计算是:

如果EleveId = 100:加权平均=(1 * 4 + 2 * 5 + 3 * 6)/(1 + 2如果EleveId = 102:加权平均值=(1 * 3.8 + 2 * 3.5),则加权平均=(1 * 4.2 + 3 * 5.4)/(1 + 3)= 5.1
如果EleveId = + 3 * 2)/(1 + 2 + 3)= 2.8

回答

2

在XPath 1.0使用

sum($currentBranche//Note[EleveId=$currentEleveId]/Valeur[number(.)=number(.)]) 

div 

    count($currentBranche//Note[EleveId=$currentEleveId]/Valeur) 

在XPath 2.0(XQuery中)使用

round(avg($currentBranche//Note[EleveId=$currentEleveId]/Valeur 
              [number(.)=number(.)])*100 
    ) div 100 

如果所有Valeur值被保证是浇注料作为xs:decimal,然后使用:

avg($currentBranche//Note[EleveId=$currentEleveId]/Valeur 
               [castable as xs:decimal] 
                /xs:decimal(.) 
    ) 

在这种情况下不会有(NotI位ceable)丢失精度,您可以稍后使用format-number()函数来获取小数点后的所需数字位数。


二,生产 “加权平均”

鉴于所提供的XML文档

<Examens> 
    <Examen> 
     <ExamenId>1</ExamenId> 
     <Coef>1</Coef> 
     <Notes> 
      <Note> 
       <EleveId>100</EleveId> 
       <Valeur>4</Valeur> 
      </Note> 
      <Note> 
       <EleveId>101</EleveId> 
       <Valeur>4.2</Valeur> 
      </Note> 
      <Note> 
       <EleveId>102</EleveId> 
       <Valeur>3.8</Valeur> 
      </Note> 
     </Notes> 
    </Examen> 
    <Examen> 
     <ExamenId>2</ExamenId> 
     <Coef>2</Coef> 
     <Notes> 
      <Note> 
       <EleveId>100</EleveId> 
       <Valeur>5</Valeur> 
      </Note> 
      <Note> 
       <EleveId>101</EleveId> 
       <Valeur/> 
      </Note> 
      <Note> 
       <EleveId>102</EleveId> 
       <Valeur>3.5</Valeur> 
      </Note> 
     </Notes> 
    </Examen> 
    <Examen> 
     <ExamenId>3</ExamenId> 
     <Coef>3</Coef> 
     <Notes> 
      <Note> 
       <EleveId>100</EleveId> 
       <Valeur>6</Valeur> 
      </Note> 
      <Note> 
       <EleveId>101</EleveId> 
       <Valeur>5.4</Valeur> 
      </Note> 
      <Note> 
       <EleveId>102</EleveId> 
       <Valeur>2</Valeur> 
      </Note> 
     </Notes> 
    </Examen> 
</Examens> 

这个XPath 2.0表达产生的加权平均:

for $elevId in distinct-values(/*/*/*/*/EleveId) 
    return 
     round(100* 
      (sum(/*/*/*/Note 
        [EleveId eq $elevId 
        and number(Valeur) eq number(Valeur) 
        ] 
         /(Valeur * ../../Coef) 
       ) 
      div 
       sum(/*/*/*/Note 
        [EleveId eq $elevId 
        and number(Valeur) eq number(Valeur) 
        ] 
        /../../Coef 
       ) 
      ) 
      ) 
    div 100 

和预期的,正确结果产生

5.33 5.1 2.8 
+0

感谢您的帮助!我不知道“数字(。)=数字(。)”这个技巧来摆脱空字符串。这解决了我的问题的第二部分,但(我的错误:一个问题在一个问题)不是第一部分:如何计算**加权**平均值,使用放置在相对路径中的权重(./../ ../Coef)?我真的不知道如何用XPath/XQuery表达式来实现。 – cbosson

+0

@cbosson,您尚未提供任何名为'Coef'的元素的XML文档。如果您编辑问题并提供现在丢失的源XML文档,答案不会很困难。请。 –

+0

@cbosson,我在回答中添加了第二部分,显示我认为是产生加权平均数的最简单方法。 –