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

XSL处理XML:保留首个div1并继承type属性报错求助

问题解决:修复XSL中div1属性设置的错误

问题背景

处理包含大量空div1元素的TEI XML集合,需实现两个需求:

  • 移除除首个div1外的所有div1元素
  • 将<text>元素的type属性值填充到首个<div1>的type属性中

源XML示例片段:

<text type="letter"  xmlns="http://www.tei-c.org/ns/1.0">
      <body>
         <pb n="1" facs="stefansson-wrangel-09-21-010-001"/>
         <div1 type="">
            <p corresp="TTP32407168P0">
               <add>
                  <hi rend="underline">Noice</hi>
               </add>
            </p>
            <p corresp="TTP32407168P1">
               <date when="1923-02-02">February 2, 1923</date>
            </p>
            <p corresp="TTP32407168P2">Dear Mr. <persName key="S32010887">Stefansson</persName>:
</p>
            <p corresp="TTP32407168P3">
               <persName key="S32010970">Joe Bernard</persName> left Monday. His present intention<lb/>
is to go to Boston, then on to Montreal, where he will spend the greater<lb/>
part of the winter. <persName key="S32010970">Joe</persName> plans to try to get museums, sportsmen, or anyone<lb/>
else to finance a trip to the Arctic, (preferably <placeName key="S32010957">Coronation Gulf</placeName>), although<lb/>
if he hears from you in the meantime he will go to <placeName key="S32010932">Wrangel</placeName>.
</p>
...
</div1>

原XSL代码已实现移除多余div1,但设置属性时报错:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  xpath-default-namespace="http://www.tei-c.org/ns/1.0"
   xmlns="http://www.tei-c.org/ns/1.0"
   version="3.0">
   
   <xsl:output method="xml" indent="yes"/>
   
   <xsl:variable name="genre" select="text/@type"></xsl:variable>
   
   <xsl:template match="node()|@*">
      <xsl:copy>
         <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
   </xsl:template>
   
   <xsl:template match="div1[position()!=1]">
      <xsl:apply-templates select="node()"/>
   </xsl:template>
   
   <xsl:template match="div1[position()=1]">
      <xsl:attribute name="type">
         <xsl:value-of select="$genre"/>
      </xsl:attribute>
   </xsl:template>
</xsl:stylesheet>

错误提示:An attribute node (type) cannot be created after a child of the containing element. Most recent element start tag was output at line 12 of module remove-extra-divs.xsl

错误原因

原代码中匹配首个div1的模板直接输出type属性,但没有先复制div1元素本身,违反了XSLT的规则:属性节点必须紧跟在所属元素的开始标签之后,不能在子节点之后创建。同时该模板还会丢失div1的所有子节点。

修正后的XSL代码

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                xpath-default-namespace="http://www.tei-c.org/ns/1.0"
                xmlns="http://www.tei-c.org/ns/1.0"
                version="3.0">
   
   <xsl:output method="xml" indent="yes"/>
   
   <!-- 正确获取根text元素的type属性 -->
   <xsl:variable name="genre" select="/text/@type"/>
   
   <!-- 身份模板:默认复制所有节点和属性 -->
   <xsl:template match="node()|@*">
      <xsl:copy>
         <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
   </xsl:template>
   
   <!-- 移除除首个div1外的所有div1标签,保留其内容 -->
   <xsl:template match="div1[position()!=1]">
      <xsl:apply-templates select="node()"/>
   </xsl:template>
   
   <!-- 替换首个div1的type属性值 -->
   <xsl:template match="div1[position()=1]/@type">
      <xsl:attribute name="type">
         <xsl:value-of select="$genre"/>
      </xsl:attribute>
   </xsl:template>
</xsl:stylesheet>

关键改动说明

  1. 修正属性设置逻辑:不再直接输出属性,而是匹配首个div1的type属性,替换其值。这样身份模板会先复制div1元素,再处理属性,符合XSLT的节点输出顺序规则。
  2. 确保变量路径准确:将$genre的选择路径明确为/text/@type,确保从根节点的text元素获取type属性值(避免上下文导致的取值错误)。
  3. 保留div1的子节点:通过身份模板和属性替换模板的配合,既修改了type属性,又完整保留了div1的所有内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 00:22:35