如何计算XPath或XQuery中的加权平均值?

时间:2013-01-02 12:30:11

标签: xpath xquery orbeon xforms xpath-2.0

我需要在XForms表单中计算一个简单的加权平均值。如何使用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>

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

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

[EDITED]

正确的计算是:

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

1 个答案:

答案 0 :(得分: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(.)
   )

在这种情况下,不会出现(明显的)精度损失,您可以稍后使用format-number()函数来获得小数点后的所需位数。


<强> II。制作“加权平均值”:

鉴于提供的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