XSLT实现XML转HTML:修改sub为num并复制元素的方法
XSLT转换XML需求解决方案
原始XML
<main> <sect1> <line>Some text<sub value="4">Sub number 4.</sub>. And some more text<sub value="5">Sub number five.</sub>.</line> <line>Yet more text<sub value="6">Sub number 6.</sub>.</line> </sect1> <sect1> <line>Would you believe yet more text<sub value="8">Eighth sub.</sub>.</line> <line>Incredible, there's more<sub value="9">Good ol' sub number 9.</sub>.</line> </sect1> </main>
目标转换结果
<main> <sect1> <line>Some text<num>4</num>. And some more text<num>5</num>.</line> <line>Yet more text<num>6</num>.</line> <sub>4 Sub number 4.</sub> <sub>5 Sub number five.</sub> <sub>6 Sub number 6.</sub> </sect1> <sect1> <line>Would you believe yet more text<num>8</num>.</line> <line>Incredible, there's more<num>9</num>.</line> <sub>8 Eighth sub.</sub> <sub>9 Good ol' sub number 9.</sub> </sect1> </main>
具体需求
- 将
line标签内嵌套的sub元素转换为num元素,仅保留其value属性的文本内容 - 把所有
sub元素以“value值 + 空格 + 原sub文本内容”的形式,追加到每个sect1下所有line元素之后
解决方案
使用以下完整XSLT即可实现需求:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 身份模板:默认复制所有未被特殊匹配的节点和属性 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- 处理line内部的sub:替换为num标签,仅输出value属性值 --> <xsl:template match="line/sub"> <num> <xsl:value-of select="@value"/> </num> </xsl:template> <!-- 处理sect1节点:先输出所有line,再生成汇总的sub元素 --> <xsl:template match="sect1"> <xsl:copy> <!-- 先输出所有line(此时line内的sub已转为num) --> <xsl:apply-templates select="line"/> <!-- 遍历当前sect1下所有sub,生成目标格式的sub元素 --> <xsl:for-each select=".//sub"> <sub> <xsl:value-of select="concat(@value, ' ', .)"/> </sub> </xsl:for-each> </xsl:copy> </xsl:template> </xsl:stylesheet>
代码说明
- 身份模板:作为基础模板,保证XML中未被自定义模板匹配的节点、属性都原样复制,维持原有结构。
- line内部sub处理模板:精准匹配
line下的sub元素,将其替换为num标签,只提取value属性值,完成第一个需求。 - sect1处理模板:先复制
sect1标签,输出所有处理后的line元素,再遍历当前sect1下所有sub节点,拼接value和原文本生成新的sub元素,追加到line之后,完成第二个需求。
内容的提问来源于stack exchange,提问作者lordmurf
相关产品推荐
相关产品推荐

