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

XSL转换问题:如何获取CPU、Memory指标的最值及对应时间

嘿,没问题,我来帮你搞定这个XSLT转换需求——从你的XML数据里提取指定<sample>元素的<value>最值,以及对应的@time属性值,最终输出成清晰的HTML表格。下面分两种常见的XSLT版本给出可运行的解决方案:

方案1:XSLT 2.0(推荐,语法更简洁直观)

适合支持XSLT 2.0及以上的处理器(比如Saxon),代码逻辑清晰,容易维护:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" encoding="UTF-8" indent="yes"/>

  <xsl:template match="/root">
    <html>
      <body>
        <table border="1">
          <tr>
            <th>监控类型</th>
            <th>最小值</th>
            <th>最小值对应时间</th>
            <th>最大值</th>
            <th>最大值对应时间</th>
          </tr>
          <!-- 分组:将含cpu的归为一组,memory单独一组 -->
          <xsl:for-each-group select="sample[@label = 'memory' or contains(@label, 'cpu')]" 
                              group-by="if (contains(@label, 'cpu')) then 'cpu组' else @label">
            <tr>
              <td><xsl:value-of select="current-grouping-key()"/></td>
              <!-- 计算当前组的最小值 -->
              <xsl:variable name="min-val" select="min(current-group()/value)"/>
              <td><xsl:value-of select="$min-val"/></td>
              <td><xsl:value-of select="current-group()[value = $min-val]/@time"/></td>
              <!-- 计算当前组的最大值 -->
              <xsl:variable name="max-val" select="max(current-group()/value)"/>
              <td><xsl:value-of select="$max-val"/></td>
              <td><xsl:value-of select="current-group()[value = $max-val]/@time"/></td>
            </tr>
          </xsl:for-each-group>
        </table>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

关键逻辑说明:

  • 用@label = 'memory' or contains(@label, 'cpu')精准筛选目标<sample>元素
  • 通过group-by将所有含cpu的样本归为同一组,memory样本单独成组
  • 用min()/max()直接计算组内<value>的最值,再通过current-group()[value = 最值]定位到对应节点,提取@time

方案2:XSLT 1.0(兼容老版本处理器)

如果你的环境只支持XSLT 1.0(比如旧版的MSXML),可以用Muenchian分组法实现,代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" encoding="UTF-8" indent="yes"/>

  <!-- 定义分组键:按cpu组/memory分组 -->
  <xsl:key name="sample-group" match="sample[@label = 'memory' or contains(@label, 'cpu')]"
           use="if (contains(@label, 'cpu')) then 'cpu组' else @label"/>

  <xsl:template match="/root">
    <html>
      <body>
        <table border="1">
          <tr>
            <th>监控类型</th>
            <th>最小值</th>
            <th>最小值对应时间</th>
            <th>最大值</th>
            <th>最大值对应时间</th>
          </tr>
          <!-- 遍历唯一分组键 -->
          <xsl:for-each select="sample[@label = 'memory' or contains(@label, 'cpu')]
                                 [generate-id() = generate-id(key('sample-group', if (contains(@label, 'cpu')) then 'cpu组' else @label)[1])]">
            <xsl:variable name="group-key" select="if (contains(@label, 'cpu')) then 'cpu组' else @label"/>
            <xsl:variable name="current-group" select="key('sample-group', $group-key)"/>
            <tr>
              <td><xsl:value-of select="$group-key"/></td>
              <!-- 计算最小值:对组内value排序后取第一个 -->
              <xsl:variable name="sorted-min">
                <xsl:for-each select="$current-group">
                  <xsl:sort select="value" data-type="number" order="ascending"/>
                  <xsl:if test="position() = 1">
                    <time><xsl:value-of select="@time"/></time>
                    <val><xsl:value-of select="value"/></val>
                  </xsl:if>
                </xsl:for-each>
              </xsl:variable>
              <td><xsl:value-of select="$sorted-min/val"/></td>
              <td><xsl:value-of select="$sorted-min/time"/></td>
              <!-- 计算最大值:对组内value排序后取最后一个 -->
              <xsl:variable name="sorted-max">
                <xsl:for-each select="$current-group">
                  <xsl:sort select="value" data-type="number" order="descending"/>
                  <xsl:if test="position() = 1">
                    <time><xsl:value-of select="@time"/></time>
                    <val><xsl:value-of select="value"/></val>
                  </xsl:if>
                </xsl:for-each>
              </xsl:variable>
              <td><xsl:value-of select="$sorted-max/val"/></td>
              <td><xsl:value-of select="$sorted-max/time"/></td>
            </tr>
          </xsl:for-each>
        </table>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

关键逻辑说明:

  • 用<xsl:key>定义分组规则,实现类似XSLT 2.0的分组效果
  • 通过generate-id()判断当前节点是否是分组的第一个节点,避免重复处理
  • 对组内节点按<value>排序,取第一个(最小值)或最后一个(最大值)节点,提取对应的@time和<value>

测试用XML示例(补全你提供的片段)

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <sample time="14" label="cpu_0"><value>22</value></sample>
  <sample time="14" label="cpu_2"><value>6</value></sample>
  <sample time="1" label="cpu_2"><value>4</value></sample>
  <sample time="5" label="memory"><value>1024</value></sample>
  <sample time="8" label="memory"><value>2048</value></sample>
  <sample time="3" label="cpu_1"><value>15</value></sample>
</root>

转换后HTML效果

最终生成的HTML表格会是这样:

监控类型最小值最小值对应时间最大值最大值对应时间
cpu组412214
memory1024520488

额外提示

如果存在多个节点的<value>等于最值(比如两个不同时间的cpu样本value都是4),你可以修改代码输出所有对应的时间:

  • XSLT 2.0:把<xsl:value-of select="current-group()[value = $min-val]/@time"/>改成<xsl:value-of select="current-group()[value = $min-val]/@time" separator=", "/>
  • XSLT 1.0:用<xsl:for-each>遍历所有符合条件的节点,拼接@time值

内容的提问来源于stack exchange,提问作者Jakub Oškera

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:49:59