基于XSLT 2.0为匹配脚注的Test模板属性添加序号
XSLT 2.0 实现指定属性添加脚注序号
输入XML结构
<ROOT> <TEMPLATE style="test"> <ATTRIBUTE name="Color"><VALUE><UNIT>B</UNIT><UNIT>lack</UNIT></VALUE></ATTRIBUTE> </TEMPLATE> <TEMPLATE style="test"> <ATTRIBUTE name="Something"><VALUE>1235</VALUE></ATTRIBUTE> <ATTRIBUTE name="Name"><VALUE><UNIT>Hello</UNIT></VALUE></ATTRIBUTE> <ATTRIBUTE name="Height"><VALUE>12</VALUE></ATTRIBUTE> </TEMPLATE> <TEMPLATE style="something-else"> <ATTRIBUTE name="Test"><VALUE>Hey</VALUE></ATTRIBUTE> </TEMPLATE> <TEMPLATE style="footnotes"> <ATTRIBUTE name="FOOTNOTE_Test"><VALUE>not-relevant</VALUE></ATTRIBUTE> <ATTRIBUTE name="FOOTNOTE_Name"><VALUE>whatever</VALUE></ATTRIBUTE> <ATTRIBUTE name="FOOTNOTE_Color"><VALUE>Some value</VALUE></ATTRIBUTE> </TEMPLATE> </ROOT>
需求说明
- 针对
style="test"的<TEMPLATE>中的<ATTRIBUTE>,若其name添加前缀FOOTNOTE_后,能匹配style="footnotes"的<TEMPLATE>中某一<ATTRIBUTE>的name,则在该<ATTRIBUTE>的<VALUE>末尾添加* {序号} - 序号按
test模板中符合条件的属性出现顺序递增,与脚注模板内的顺序无关
目标输出
<ROOT> <TEMPLATE style="test"> <ATTRIBUTE name="Color"><VALUE><UNIT>B</UNIT><UNIT>lack</UNIT> *1</VALUE></ATTRIBUTE> </TEMPLATE> <TEMPLATE style="test"> <ATTRIBUTE name="Something"><VALUE>1235</VALUE></ATTRIBUTE> <ATTRIBUTE name="Name"><VALUE><UNIT>Hello</UNIT> *2</VALUE></ATTRIBUTE> <ATTRIBUTE name="Height"><VALUE>12</VALUE></ATTRIBUTE> </TEMPLATE> <TEMPLATE style="something-else"> <ATTRIBUTE name="Test"><VALUE>Hey</VALUE></ATTRIBUTE> </TEMPLATE> <TEMPLATE style="footnotes"> <ATTRIBUTE name="FOOTNOTE_Test"><VALUE>not-relevant</VALUE></ATTRIBUTE> <ATTRIBUTE name="FOOTNOTE_Name"><VALUE>whatever</VALUE></ATTRIBUTE> <ATTRIBUTE name="FOOTNOTE_Color"><VALUE>Some value</VALUE></ATTRIBUTE> </TEMPLATE> </ROOT>
解决方案(XSLT 2.0代码)
<xsl:stylesheet version="2.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> <!-- 收集脚注模板的所有属性名 --> <xsl:variable name="footnoteAttrNames" select="/ROOT/TEMPLATE[@style='footnotes']/ATTRIBUTE/@name"/> <!-- 筛选test模板中符合脚注匹配条件的属性节点 --> <xsl:variable name="matchedTestAttrs" select="/ROOT/TEMPLATE[@style='test']/ATTRIBUTE[contains($footnoteAttrNames, concat('FOOTNOTE_', @name))]"/> <!-- 处理test模板下的VALUE节点 --> <xsl:template match="TEMPLATE[@style='test']/ATTRIBUTE/VALUE"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> <!-- 判断当前属性是否需要添加序号 --> <xsl:if test="parent::ATTRIBUTE[contains($footnoteAttrNames, concat('FOOTNOTE_', @name))]"> <xsl:text> *</xsl:text> <!-- 按出现顺序获取序号 --> <xsl:value-of select="index-of($matchedTestAttrs, parent::ATTRIBUTE)"/> </xsl:if> </xsl:copy> </xsl:template> </xsl:stylesheet>
代码解释
- 默认复制规则:保留所有原始节点和属性,仅修改需要处理的
<VALUE>节点内容 - 变量定义:
footnoteAttrNames:批量提取脚注模板中所有<ATTRIBUTE>的name属性值matchedTestAttrs:筛选出test模板中,添加FOOTNOTE_前缀后能匹配脚注属性的所有<ATTRIBUTE>节点,按出现顺序存储
- VALUE节点处理:
- 先复制VALUE节点的原有内容,再判断其父节点
<ATTRIBUTE>是否在匹配列表中 - 使用
index-of函数获取该属性在匹配列表中的位置,作为序号追加到VALUE末尾
- 先复制VALUE节点的原有内容,再判断其父节点
内容的提问来源于stack exchange,提问作者LHark
相关产品推荐
相关产品推荐

