编写XSL复制元素及其关联处理指令的技术需求
低侵入式增强MapForce生成XSLT以复制关联处理指令
核心需求回顾
基于现有MapForce生成的XSLT(大量使用xsl:for-each),需实现:
- 复制指定元素与其前一个元素之间的前置处理指令(作为元素注解)
- 通过处理指令中的ID(如
<?format-number id?>)关联并复制对应目标元素的处理指令 - 处理文档末尾无关联元素的孤立处理指令
实现方案
1. 定义索引Key(用于ID关联的处理指令)
先定义key,快速匹配与目标元素ID对应的处理指令:
<xsl:key name="pi-by-target-id" match="processing-instruction('format-number')" use="substring-after(., ' ')" />
说明:
substring-after(., ' ')提取处理指令中空格后的ID值作为索引键,匹配目标元素的@id属性。若处理指令格式不同,可调整此表达式。
2. 编写处理前置处理指令的模板
提取当前元素与前一个同级元素(或根节点)之间的所有处理指令:
<xsl:template name="copy-preceding-pis"> <xsl:param name="current-element" /> <xsl:variable name="prev-sibling" select="$current-element/preceding-sibling::*[1]" /> <xsl:choose> <!-- 非首个元素:取前一个元素与当前元素之间的处理指令 --> <xsl:when test="$prev-sibling"> <xsl:copy-of select="$prev-sibling/following-sibling::processing-instruction()[. << $current-element]" /> </xsl:when> <!-- 首个元素:取根节点下、当前元素之前的所有处理指令 --> <xsl:otherwise> <xsl:copy-of select="$current-element/../processing-instruction()[. << $current-element]" /> </xsl:otherwise> </xsl:choose> </xsl:template>
说明:使用XSLT 2.0的
<<节点顺序运算符,精准定位符合位置要求的处理指令。
3. 编写处理ID关联处理指令的模板
通过key快速匹配并复制与目标元素ID对应的处理指令:
<xsl:template name="copy-associated-pis"> <xsl:param name="target-id" /> <xsl:copy-of select="key('pi-by-target-id', $target-id)" /> </xsl:template>
4. 低侵入式整合到现有for-each逻辑
原有MapForce生成的代码通常为:
<xsl:for-each select="your-target-element"> <xsl:copy-of select="." /> </xsl:for-each>
只需在xsl:copy-of前插入模板调用,不修改原有选择逻辑:
<xsl:for-each select="your-target-element"> <!-- 复制当前元素的前置处理指令 --> <xsl:call-template name="copy-preceding-pis"> <xsl:with-param name="current-element" select="." /> </xsl:call-template> <!-- 如果元素有ID,复制关联的处理指令 --> <xsl:if test="@id"> <xsl:call-template name="copy-associated-pis"> <xsl:with-param name="target-id" select="@id" /> </xsl:call-template> </xsl:if> <!-- 保留原有复制元素的逻辑 --> <xsl:copy-of select="." /> </xsl:for-each>
5. 处理文档末尾的孤立处理指令
在所有for-each执行完成后,添加以下代码复制无后续关联元素的处理指令:
<xsl:copy-of select="/processing-instruction()[not(following-sibling::*)]" />
注意事项
- 确保运行环境支持XSLT 2.0(如Saxon 9及以上版本)
- 若处理指令类型不是
format-number,可修改key的match条件为processing-instruction()匹配所有类型,或指定其他指令名称 - 模板可直接添加到现有XSLT的
<xsl:stylesheet>根节点下,无需修改原有模板逻辑
内容的提问来源于stack exchange,提问作者sparty02
相关产品推荐
相关产品推荐

