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

XSL更新seg的xml:id属性时position()取值异常问题求助

解决XSLT中position()始终返回1的问题

你的问题核心在于对XSLT模板上下文和position()函数的理解偏差,还有变量定义的小错误,咱们一步步来修正:

1. 先修正变量定义的语法错误

你写的<xsl:variable name="var_val" select="tei:document/n@"/>是语法错误,正确的写法应该是获取document元素的n属性,比如:

<xsl:variable name="doc-n" select="/tei:document/@n"/>

这里用绝对路径/tei:document确保能精准定位到根节点的n属性,变量名也更直观好懂。

2. 为什么position()总是返回1?

你的模板匹配的是tei:seg/@xml:id属性节点,当处理每个属性时,当前上下文是单个属性节点——也就是说,每次模板只处理一个属性,这个属性在自己的上下文序列里排第1,所以position()自然返回1。你需要的是seg元素在同级兄弟中的位置,就得基于seg的上下文来计算,而非属性的上下文。

解决方案1:匹配seg元素而非属性(更推荐)

直接匹配tei:seg元素,在输出时重新生成xml:id属性,这样position()就能正确返回当前seg在同级兄弟中的位置:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:tei="http://example.com/tei">
  <xsl:output method="xml" indent="yes"/>
  
  <!-- 默认模板:复制所有未被自定义模板匹配的节点和属性 -->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:variable name="doc-n" select="/tei:document/@n"/>

  <!-- 自定义seg模板,重新生成xml:id -->
  <xsl:template match="tei:seg">
    <seg xml:id="{$doc-n}-{position()}">
      <!-- 复制seg的其他属性和子节点,排除原xml:id -->
      <xsl:apply-templates select="@*[not(local-name()='xml:id')]|node()"/>
    </seg>
  </xsl:template>
</xsl:stylesheet>

这里的核心逻辑:

  • 默认模板负责保留文档的其他结构,只修改seg的xml:id
  • 在seg的模板中,position()的上下文是所有同级的seg元素,所以能正确返回1、2、3、4...

解决方案2:在属性模板中手动计算位置

如果你坚持要匹配属性节点,可以通过统计当前seg的前置兄弟seg数量来得到位置:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:tei="http://example.com/tei">
  <xsl:output method="xml" indent="yes"/>
  
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:variable name="doc-n" select="/tei:document/@n"/>

  <xsl:template match="tei:seg/@xml:id">
    <xsl:attribute name="xml:id">
      <xsl:value-of select="$doc-n"/>
      <xsl:text>-</xsl:text>
      <!-- 统计当前seg前面有多少个同级seg,加1就是它的位置 -->
      <xsl:value-of select="count(parent::tei:seg/preceding-sibling::tei:seg) + 1"/>
    </xsl:attribute>
  </xsl:template>
</xsl:stylesheet>

验证结果

两种方案运行后,都会生成你预期的结果:

<document n="foo" xmlns="http://example.com/tei">
  <body>
    <seg xml:id="foo-1">some text</seg>
    <seg xml:id="foo-2">some text</seg>
    <seg xml:id="foo-3">some text</seg>
    <seg xml:id="foo-4">some text</seg>
  </body>
</document>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:48:51