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

如何在XPath或XQuery中计算加权平均值?,xpath,xquery,orbeon,xforms,xpath-2.0,Xpath,Xquery,Orbeon,Xforms,Xpath 2.0,我需要在XForms表单中计算一个简单的加权平均值。如何使用XPath和/或XQuery以优雅的声明方式实现这一点 [已编辑]这是源XML文档: <Examens> <Examen> <ExamenId>1</ExamenId> <Coef>1</Coef> <Notes> <Note> &

我需要在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
为空字符串的节点。例如,在下面使用XPath
avg()
函数进行的简单平均值计算中,如果一个节点的内容是空字符串,则出现错误(“无法将“”转换为双精度”)。这是一个问题,因为节点存在(它是模型实例的一部分),并且当用户尚未输入值时,值是空字符串

<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
在XPath 1.0中使用

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

 div

  count($currentBranche//Note[EleveId=$currentEleveId]/Valeur)
round(avg($currentBranche//Note[EleveId=$currentEleveId]/Valeur
                                             [number(.)=number(.)])*100
      ) div 100
<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>
5.33 5.1 2.8
在Xpath 2.0(XQuery)中使用

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

 div

  count($currentBranche//Note[EleveId=$currentEleveId]/Valeur)
round(avg($currentBranche//Note[EleveId=$currentEleveId]/Valeur
                                             [number(.)=number(.)])*100
      ) div 100
<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>
5.33 5.1 2.8
如果所有
Valeur
值都保证可以按
xs:decimal
进行强制转换,则使用:

avg($currentBranche//Note[EleveId=$currentEleveId]/Valeur
                                                 [castable as xs:decimal]
                                                    /xs:decimal(.)
   )
   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
在这种情况下,精度不会(明显)降低,您可以稍后使用
format-number()
函数获取小数点后所需的位数


II。产生“加权平均数”

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

 div

  count($currentBranche//Note[EleveId=$currentEleveId]/Valeur)
round(avg($currentBranche//Note[EleveId=$currentEleveId]/Valeur
                                             [number(.)=number(.)])*100
      ) div 100
<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>
5.33 5.1 2.8
给定提供的XML文档

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

 div

  count($currentBranche//Note[EleveId=$currentEleveId]/Valeur)
round(avg($currentBranche//Note[EleveId=$currentEleveId]/Valeur
                                             [number(.)=number(.)])*100
      ) div 100
<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>
5.33 5.1 2.8
并生成预期的正确结果

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

 div

  count($currentBranche//Note[EleveId=$currentEleveId]/Valeur)
round(avg($currentBranche//Note[EleveId=$currentEleveId]/Valeur
                                             [number(.)=number(.)])*100
      ) div 100
<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>
5.33 5.1 2.8

谢谢你的帮助!我不知道去除空字符串的诀窍。这解决了我问题的第二部分,但(我的错误:一个问题中有两个问题)不是第一部分:如何使用从值(../../../Coef)放置在相对路径上的权重计算加权平均值?我真的不知道如何使用XPath/XQuery表达式。@cbosson,您没有提供任何包含名为
Coef
的元素的XML文档。如果您编辑问题并提供现在缺少的源XML文档,那么答案不会很难。请。@cbosson,我在我的答案中添加了第二部分,说明了我认为最简单的加权平均方法。加权平均不是这样计算的。正确的公式应该是
sum(/*/num(val*weight))
除以
sum(/*num/val)
,在这个例子中应该=4。@Flynn1179你想计算加权平均数的方法是正确的,但我认为你答案的第二个公式应该是
sum(/*/num/weight)
,不是吗?无论如何,谢谢你的意见!