XSLT 2.0节点拆分需求:按分隔符拆分para节点并保留子节点
XSLT 2.0 节点拆分解决方案:按分隔符拆分并保留原结构
输入XML
<?xml version="1.0" encoding="UTF-8"?> <root xmlns:xlink="http://www.w3.org/1999/xlink"> <para id="pa3" class="para_index"> <alinea>Achard de Saint-Victor : <marquage typemarq="italique"><liensimple id="l3" xlink:href="xxx://numero:isbn:xxxx/article:page:397">397</liensimple></marquage></alinea> </para> </root>
期望输出XML
<?xml version="1.0" encoding="UTF-8"?> <root xmlns:xlink="http://www.w3.org/1999/xlink"> <para id="pa3"> <listerelation type="1"> <lrsource> <alinea>Achard de Saint-Victor</alinea> </lrsource> <lrcible> <alinea><marquage typemarq="italique"><liensimple id="l3" xlink:href="xxx://numero:isbn:xxxx/article:page:397">397</liensimple></marquage> </alinea> </lrcible> </listerelation> </para> </root>
解决方案XSLT代码
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xlink="http://www.w3.org/1999/xlink"> <xsl:output method="xml" indent="yes" encoding="UTF-8"/> <!-- 全局默认复制规则:保留未特殊处理的节点与属性 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- 处理目标para节点,重构内部结构 --> <xsl:template match="para"> <para id="{@id}"> <listerelation type="1"> <!-- 获取alinea下的所有子节点 --> <xsl:variable name="alinea-nodes" select="alinea/node()"/> <!-- 定位包含分隔符" : "的文本节点 --> <xsl:variable name="sep-node" select="$alinea-nodes[self::text()[contains(., ' : ')]]"/> <!-- 拆分文本节点为前后两段 --> <xsl:variable name="split-text" select="tokenize($sep-node, ' : ')"/> <lrsource> <alinea> <!-- 复制分隔符前的所有节点,加上拆分后的前半段文本 --> <xsl:apply-templates select="$alinea-nodes[. << $sep-node]"/> <xsl:value-of select="$split-text[1]"/> </alinea> </lrsource> <lrcible> <alinea> <!-- 加上拆分后的后半段文本,复制分隔符后的所有节点 --> <xsl:value-of select="$split-text[2]"/> <xsl:apply-templates select="$alinea-nodes[. >> $sep-node]"/> </alinea> </lrcible> </listerelation> </para> </xsl:template> <!-- 跳过原alinea节点的默认复制,避免重复生成 --> <xsl:template match="para/alinea"/> </xsl:stylesheet>
关键逻辑说明
- 默认复制模板:保证XML中未被单独处理的节点、属性和命名空间完整保留,避免信息丢失。
- 节点拆分核心:
- 定位到包含目标分隔符
:的文本节点,而非直接拆分整个字符串,以此保留原节点结构。 - 使用
tokenize()拆分目标文本节点,再结合节点位置比较(<</>>),将分隔符前后的节点和文本分别归入对应标签。
- 定位到包含目标分隔符
- 属性处理:重构
<para>标签时仅保留id属性,移除原有的class属性。
内容的提问来源于stack exchange,提问作者Marius Rusu
相关产品推荐
相关产品推荐

