3

我需要以 XForms 形式计算一个简单的加权平均值。如何使用 XPath 和/或 XQuery 以优雅和声明性的方式做到这一点?

[编辑] 这是源 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空字符串的节点。例如,在下面使用 XPathavg()函数的简单平均计算中,如果一个节点的内容是空字符串,我会得到一个错误(“无法将 '' 转换为 double”)。这是一个问题,因为节点存在(它是模型实例的一部分)并且当用户尚未输入值时该值是空字符串。

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

[编辑]

正确的计算是:

如果 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

4

1 回答 1

4

在 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()函数来获取小数点后所需的位数。


二、产生“加权平均”

鉴于提供的 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
于 2013-01-02T15:27:46.063 回答