You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:使用XSLT计算一组数值的中位数

XSLT计算数值组的中位数解决方案

核心逻辑

计算中位数的关键步骤:

  • 先对目标数值组按数值大小排序(避免字符串排序导致的错误,比如"10"排在"8"前面)
  • 根据数值数量的奇偶性分别处理:
    • 奇数个数值:取排序后中间位置的数值(位置为(总数+1)/2,因为XSLT节点的position()从1开始)
    • 偶数个数值:取排序后中间两个数值的平均值

输入XML示例

假设你的输入结构如下:

<Employees>
  <Employee ID="123">
    <PSQ3_Values>8</PSQ3_Values>
    <PSQ3_Values>6</PSQ3_Values>
    <PSQ3_Values>8</PSQ3_Values>
  </Employee>
  <Employee ID="456">
    <PSQ3_Values>9</PSQ3_Values>
    <PSQ3_Values>10</PSQ3_Values>
  </Employee>
</Employees>

XSLT 2.0 实现(推荐,语法更简洁)

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text" indent="yes"/>

  <!-- 遍历每个员工计算中位数 -->
  <xsl:template match="/Employees">
    <xsl:for-each select="Employee">
      <xsl:variable name="empId" select="@ID"/>
      <!-- 获取并转换为数值类型后排序 -->
      <xsl:variable name="sortedValues" select="PSQ3_Values/number(.)[sort()]"/>
      <xsl:variable name="valueCount" select="count($sortedValues)"/>

      <!-- 计算中位数 -->
      <xsl:variable name="median">
        <xsl:choose>
          <!-- 奇数个数值 -->
          <xsl:when test="$valueCount mod 2 = 1">
            <xsl:value-of select="$sortedValues[position() = ($valueCount + 1) div 2]"/>
          </xsl:when>
          <!-- 偶数个数值 -->
          <xsl:otherwise>
            <xsl:value-of select="($sortedValues[position() = $valueCount div 2] + $sortedValues[position() = ($valueCount div 2) + 1]) div 2"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:variable>

      <!-- 输出结果 -->
      <xsl:text>员工ID</xsl:text>
      <xsl:value-of select="$empId"/>
      <xsl:text>的PSQ3中位数:</xsl:text>
      <xsl:value-of select="$median"/>
      <xsl:text>&#10;</xsl:text>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

关键说明

  • $sortedValues:先将PSQ3_Values节点转换为数值类型,再用sort()函数排序,确保是数值排序而非字符串排序
  • 奇数长度处理:3个数值时,(3+1)/2=2,取排序后的第2个节点(对应数值8)
  • 偶数长度处理:2个数值时,取第1和第2个节点的平均值,(9+10)/2=9.5

XSLT 1.0 实现(适配旧版处理器)

XSLT 1.0没有内置排序函数,需要用递归模板实现排序,同时需要将结果树片段转为节点集(不同处理器命名空间可能不同,示例用msxsl):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt">
  <xsl:output method="text" indent="yes"/>

  <!-- 主模板遍历员工 -->
  <xsl:template match="/Employees">
    <xsl:for-each select="Employee">
      <xsl:variable name="empId" select="@ID"/>
      <xsl:variable name="rawValues" select="PSQ3_Values"/>
      <!-- 调用递归排序模板 -->
      <xsl:variable name="sortedNodes">
        <xsl:call-template name="sort-numeric-nodes">
          <xsl:with-param name="nodes" select="$rawValues"/>
        </xsl:call-template>
      </xsl:variable>
      <xsl:variable name="valueCount" select="count($rawValues)"/>
      <!-- 将结果树片段转为节点集 -->
      <xsl:variable name="sortedValues" select="msxsl:node-set($sortedNodes)/PSQ3_Values"/>

      <!-- 计算中位数 -->
      <xsl:variable name="median">
        <xsl:choose>
          <xsl:when test="$valueCount mod 2 = 1">
            <xsl:value-of select="$sortedValues[position() = ($valueCount + 1) div 2]"/>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="(number($sortedValues[position() = $valueCount div 2]) + number($sortedValues[position() = ($valueCount div 2) + 1])) div 2"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:variable>

      <!-- 输出结果 -->
      <xsl:text>员工ID</xsl:text>
      <xsl:value-of select="$empId"/>
      <xsl:text>的PSQ3中位数:</xsl:text>
      <xsl:value-of select="$median"/>
      <xsl:text>&#10;</xsl:text>
    </xsl:for-each>
  </xsl:template>

  <!-- 递归排序模板 -->
  <xsl:template name="sort-numeric-nodes">
    <xsl:param name="nodes"/>
    <xsl:if test="$nodes">
      <!-- 找到当前节点集中的最小值 -->
      <xsl:variable name="minNode" select="$nodes[not(number(.) > number($nodes))][1]"/>
      <PSQ3_Values><xsl:value-of select="$minNode"/></PSQ3_Values>
      <!-- 递归排序剩余节点 -->
      <xsl:call-template name="sort-numeric-nodes">
        <xsl:with-param name="nodes" select="$nodes[number(.) != number($minNode)]"/>
      </xsl:call-template>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>

注意事项

  • 如果使用Saxon等非微软处理器,需要将msxsl:node-set替换为saxon:node-set,并添加对应命名空间
  • 递归排序模板通过每次提取最小值实现排序,确保数值排序的正确性

内容的提问来源于stack exchange,提问作者Buddi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 18:24:49