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

XSLT多序列合并及XML属性值聚合问题排查与解决

解决XSLT 2.0中合并元素并处理缺失值的问题

嗨,我看了你遇到的两个问题,其实核心都是上下文节点混淆和变量引用的上下文问题,咱们一步步来搞定:

你的问题根源

  1. 找不到part元素:在$allTheProps/prop的循环里,当前上下文节点是你变量里的prop元素,不是正在处理的something节点,所以直接写select="part"自然找不到目标元素。
  2. 变量判断失效:其实XSLT 2.0完全支持在路径里用变量做判断,问题还是出在上下文不对——你在错误的节点上下文里找prop,自然匹配不到。

修正后的完整XSLT代码

我帮你调整了代码,同时把静态的prop类型改成了动态获取(更符合你的需求):

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
 <xsl:output method="xml" doctype-public="XSLT-compat" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
 <!-- 动态提取文档中所有唯一的prop类型 -->
 <xsl:variable name="allPropTypes" select="distinct-values(//prop/@type)" />

 <xsl:template match="something">
  <xsl:copy>
   <!-- 遍历所有唯一的prop类型 -->
   <xsl:for-each select="$allPropTypes">
    <xsl:variable name="currentType" select="." />
    <!-- 用属性值模板简化属性写法 -->
    <props type="{$currentType}">
     <!-- 明确指定上下文:当前something下的所有part -->
     <xsl:for-each select="current()/part">
      <xsl:choose>
       <xsl:when test="prop[@type=$currentType]">
        <xsl:value-of select="prop[@type=$currentType]" />
       </xsl:when>
       <xsl:otherwise>?</xsl:otherwise>
      </xsl:choose>
     </xsl:for-each>
    </props>
   </xsl:for-each>
  </xsl:copy>
 </xsl:template>

 <!-- 匹配根节点,触发所有something的处理 -->
 <xsl:template match="/">
  <xsl:apply-templates select="//something" />
 </xsl:template>
</xsl:transform>

关键修改说明

  • 明确上下文节点:用current()/part代替select="part",current()会指向当前正在匹配的something节点,这样就能正确找到它下面的所有part了。
  • 动态获取prop类型:distinct-values(//prop/@type)会自动从整个文档中提取所有不重复的prop/@type值,不用手动维护静态变量,更灵活。
  • 简化属性写法:用type="{$currentType}"这种属性值模板替代原来的xsl:attribute,代码更简洁。
  • 修正输出格式:把output method="html"改成method="xml",确保输出符合你期望的XML结构,避免HTML模式的自动标签闭合等问题。

如果你想保留静态变量的写法

要是你因为特殊需求必须用原来的$allTheProps静态变量,那只要提前保存当前something的上下文即可:

<xsl:template match="something">
  <xsl:copy>
    <!-- 先把当前something节点保存到变量 -->
    <xsl:variable name="currentSomething" select="." />
    <xsl:for-each select="$allTheProps/prop">
      <xsl:variable name="nodeType" select="@type"/>
      <props type="{$nodeType}">
        <!-- 通过变量指定上下文,找到正确的part -->
        <xsl:for-each select="$currentSomething/part">
          <xsl:value-of select="prop[@type=$nodeType]"/>
          <xsl:if test="not(prop[@type=$nodeType])">?</xsl:if>
        </xsl:for-each>
      </props>
    </xsl:for-each>
  </xsl:copy>
</xsl:template>

这样也能完美解决你遇到的两个问题,输出结果完全符合你的预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:28:38