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

XSLT 1.0复杂分组性能优化:非结构化XML转结构化求助

优化XSLT 1.0性能:从非结构化XML构建层级结构

需求说明

需要将平铺的非结构化XML转换为层级清晰的结构化XML,原有实现通过for-each结合全局节点匹配完成转换,但处理15000行数据时性能严重不足,需优化实现逻辑,避免低效的全局遍历。

输入非结构化XML

<Document>
  <HEADER>
    <h1>1</h1>
  </HEADER>
  <SUMMARY>
    <s1>1</s1>
  </SUMMARY>
  <SUBMISSION>
    <su1>1</su1>
  </SUBMISSION>
  <TRANSACTION>
    <tr1>1</tr1>
  </TRANSACTION>
  <TXPRICE>
    <tx1>1</tx1>
  </TXPRICE>
  <TXPRICE>
    <tx1>2</tx1>
  </TXPRICE>
  <CHARGEBACK>
    <c1>1</c1>
  </CHARGEBACK>
  <FOOTER>
    <f1>1</f1>
  </FOOTER>
</Document>

期望输出结构化XML

<HEADER>
  <h1>1</h1>
</HEADER>
<SUMMARY>
  <s1>1</s1>
  <SUBMISSION>
    <su1>1</su1>
    <TRANSACTION>
      <tr1>1</tr1>
      <TXPRICE>
        <tx1>1</tx1>
      </TXPRICE>
      <TXPRICE>
        <tx1>2</tx1>
      </TXPRICE>
    </TRANSACTION>
    <CHARGEBACK>
      <c1>1</c1>
    </CHARGEBACK>
  </SUBMISSION>
</SUMMARY>
<FOOTER>
  <f1>1</f1>
</FOOTER>

原有实现的性能问题

原有XSLT代码在每个模板中使用/Document/XXX[匹配条件]进行全局节点查询,每次匹配都要遍历整个文档的对应节点类型,数据量增大时时间复杂度呈**O(n²)**增长,导致处理大文档时速度无法接受。

原有XSLT代码

<xsl:stylesheet version="1.0">
  <xsl:template match="/">
    <Structured_Document>
      <xsl:apply-templates select="/Document/HEADER"/>
      <xsl:apply-templates select="/Document/SUMMARY"/>
      <xsl:apply-templates select="/Document/TRAILER"/>
    </Structured_Document>
  </xsl:template>
  <xsl:template match="/Document/HEADER">
    <xsl:copy>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="/Document/SUMMARY">
    <xsl:copy>
      <xsl:apply-templates/>
      <xsl:for-each select="/Document/SUBMISSION[su1/text() = current()/s1/text()]">
        <xsl:apply-templates select="."/>
      </xsl:for-each>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="/Document/SUBMISSION">
    <xsl:copy>
      <xsl:apply-templates/>
      <xsl:for-each select="/Document/TRANSACTN[tr1/text() = current()/su1/text()]">
        <xsl:apply-templates select="."/>
      </xsl:for-each>
      <xsl:for-each select="/Document/CHARGEBACK[ch1/text() = current()/tr1/text()]">
        <xsl:apply-templates select="."/>
      </xsl:for-each>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="/Document/TRANSACTN">
    <xsl:copy>
      <xsl:apply-templates/>
      <xsl:for-each select="/Document/TXNPRICING[tx1/text() = current()/tr1/text()]">
        <xsl:apply-templates select="."/>
      </xsl:for-each>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="/Document/TXNPRICING">
    <xsl:copy>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="/Document/CHARGEBACK">
    <xsl:copy>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="/Document/FOOTER">
    <xsl:copy>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="node() | @*">
    <xsl:copy>
      <xsl:apply-templates select="node() | @*"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

优化后的XSLT实现

使用XSLT 1.0的<xsl:key>创建节点索引,将全局遍历改为索引查询,大幅降低时间复杂度。以下代码基于实际场景的关联字段调整(示例中匹配字段已修正对应关系):

<xsl:stylesheet version="1.0">
  <!-- 预创建关联索引 -->
  <xsl:key name="submission-by-summary" match="SUBMISSION" use="su1"/>
  <xsl:key name="transaction-by-submission" match="TRANSACTION" use="tr1"/>
  <xsl:key name="txprice-by-transaction" match="TXPRICE" use="tx1"/>
  <xsl:key name="chargeback-by-submission" match="CHARGEBACK" use="c1"/>

  <xsl:template match="/">
    <Structured_Document>
      <xsl:apply-templates select="Document/HEADER"/>
      <xsl:apply-templates select="Document/SUMMARY"/>
      <xsl:apply-templates select="Document/FOOTER"/>
    </Structured_Document>
  </xsl:template>

  <!-- HEADER模板 -->
  <xsl:template match="HEADER">
    <xsl:copy>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>

  <!-- SUMMARY模板:通过key获取关联的SUBMISSION -->
  <xsl:template match="SUMMARY">
    <xsl:copy>
      <xsl:apply-templates/>
      <xsl:apply-templates select="key('submission-by-summary', s1)"/>
    </xsl:copy>
  </xsl:template>

  <!-- SUBMISSION模板:通过key获取关联的TRANSACTION和CHARGEBACK -->
  <xsl:template match="SUBMISSION">
    <xsl:copy>
      <xsl:apply-templates/>
      <xsl:apply-templates select="key('transaction-by-submission', su1)"/>
      <xsl:apply-templates select="key('chargeback-by-submission', su1)"/>
    </xsl:copy>
  </xsl:template>

  <!-- TRANSACTION模板:通过key获取关联的TXPRICE -->
  <xsl:template match="TRANSACTION">
    <xsl:copy>
      <xsl:apply-templates/>
      <xsl:apply-templates select="key('txprice-by-transaction', tr1)"/>
    </xsl:copy>
  </xsl:template>

  <!-- 基础复制模板 -->
  <xsl:template match="TXPRICE | CHARGEBACK | FOOTER">
    <xsl:copy>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>

  <!-- 身份模板:复制所有未匹配的节点和属性 -->
  <xsl:template match="node() | @*">
    <xsl:copy>
      <xsl:apply-templates select="node() | @*"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

优化说明

  1. 索引优化:通过<xsl:key>为每个关联层级创建索引,查询关联节点时直接调用key()函数,时间复杂度降至O(n),避免了重复遍历整个文档。
  2. 简化逻辑:去掉冗余的for-each循环,直接通过xsl:apply-templates调用关联节点的模板,代码更简洁易维护。
  3. 模板复用:合并了重复的节点复制逻辑,减少代码冗余。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 18:37:02