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

如何使用XSL统计有向无环图中的子节点数量

嘿,我来帮你搞定用XSL统计有向无环图(DAG)子节点数量的问题。首先咱们得明确需求:你是想统计每个节点的直接子节点数量(只算下一级),还是递归统计该节点下所有的后代节点总数(包含子节点、孙节点等所有层级)?我两种场景都给你准备了示例代码,你可以按需选用。

先补全你提供的XML(假设截断的item7父节点是2,完整结构如下):

<?xml version="1.0" encoding="utf-8"?>
<items>
  <item id="1"> </item>
  <item id="2"> <parent idref="1" /> </item>
  <item id="3"> <parent idref="1" /> </item>
  <item id="4"> <parent idref="3" /> </item>
  <item id="5"> <parent idref="4" /> </item>
  <item id="6"> <parent idref="3" /> </item>
  <item id="7"> <parent idref="2" /> </item>
</items>

1. 统计每个节点的直接子节点数量

这个需求比较简单,核心是用<xsl:key>建立父节点ID到子节点的映射,然后对每个节点统计匹配的子节点数量即可。下面是XSLT 1.0的实现(兼容性最好):

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <!-- 建立父ID到对应子节点的索引,方便快速查询 -->
  <xsl:key name="child-by-parent" match="item" use="parent/@idref"/>

  <xsl:template match="/items">
    <node-stats>
      <!-- 遍历所有节点,逐个统计直接子节点数 -->
      <xsl:for-each select="item">
        <node id="{@id}">
          <direct-children-count>
            <!-- 统计当前ID作为父ID的节点数量 -->
            <xsl:value-of select="count(key('child-by-parent', @id))"/>
          </direct-children-count>
        </node>
      </xsl:for-each>
    </node-stats>
  </xsl:template>
</xsl:stylesheet>

运行后你会得到类似这样的输出:

<node-stats>
  <node id="1">
    <direct-children-count>2</direct-children-count>
  </node>
  <node id="2">
    <direct-children-count>1</direct-children-count>
  </node>
  <node id="3">
    <direct-children-count>2</direct-children-count>
  </node>
  <!-- 其他节点的统计结果省略 -->
</node-stats>

2. 递归统计每个节点的所有后代节点总数

如果需要统计某个节点下所有层级的后代(比如节点1的后代包含2、3、4、5、6、7),就得用递归模板来实现。同样借助<xsl:key>来快速查找子节点,然后递归累加每个子节点的后代数:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:key name="child-by-parent" match="item" use="parent/@idref"/>

  <!-- 递归模板:计算传入节点ID的所有后代总数 -->
  <xsl:template name="count-descendants">
    <xsl:param name="node-id"/>
    <!-- 获取当前节点的所有直接子节点 -->
    <xsl:variable name="direct-children" select="key('child-by-parent', $node-id)"/>
    
    <!-- 先统计直接子节点数,再累加每个子节点的后代数 -->
    <xsl:variable name="child-descendant-counts">
      <xsl:for-each select="$direct-children">
        <count>
          <xsl:call-template name="count-descendants">
            <xsl:with-param name="node-id" select="@id"/>
          </xsl:call-template>
        </count>
      </xsl:for-each>
    </xsl:variable>
    
    <xsl:value-of select="count($direct-children) + sum($child-descendant-counts/count)"/>
  </xsl:template>

  <xsl:template match="/items">
    <node-stats>
      <xsl:for-each select="item">
        <node id="{@id}">
          <total-descendants-count>
            <xsl:call-template name="count-descendants">
              <xsl:with-param name="node-id" select="@id"/>
            </xsl:call-template>
          </total-descendants-count>
        </node>
      </xsl:for-each>
    </node-stats>
  </xsl:template>
</xsl:stylesheet>

这个模板运行后,节点1的total-descendants-count会是6(所有子节点加后代),节点3的总数是3(4、5、6),完全符合DAG的层级关系。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:03:28