如何用XSLT 1.0匹配元素属性值并求和生成新属性
XSLT新手求助:匹配属性并计算生成新属性
需求
匹配每个SOURCE元素的name属性与BLOCK元素的name属性,匹配成功后,将对应BLOCK的X属性值与SOURCE的id属性值求和,生成新的pointX属性。
输入XML
<?xml version="1.0" encoding="UTF-8"?> <puzzle> <BLOCKS> <BLOCK X="12" name="BL_01"></BLOCK> <BLOCK X="12" name="BL_02"></BLOCK> <BLOCK X="12" name="BL_03"></BLOCK> </BLOCKS> <CONNEXIONS> <CONNEXION> <SOURCE name="BL_01" id="4"></SOURCE> </CONNEXION> <CONNEXION> <SOURCE name="BL_03" id="1"></SOURCE> </CONNEXION> <CONNEXION> <SOURCE name="BL_02" id="8"> </SOURCE> </CONNEXION> </CONNEXIONS> </puzzle>
期望输出XML
<program> <lSource> <space pointX="16" ></space> </lSource> <lSource> <space pointX="13" ></space> </lSource> <lSource> <space pointX="20" ></space> </lSource> </program>
尝试的XSLT代码(无法正常运行)
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ex="http://exslt.org/dates-and-times" exclude-result-prefixes="ex"> <xsl:output version="1.0" encoding="UTF-8" standalone="yes" indent="yes" method="html"/> <xsl:strip-space elements="*"/> <xsl:template match="/"> <program> <xsl:for-each select="puzzle/CONNEXIONS/CONNEXION"> <lSource> <space> <xsl:for-each select="puzzle/CONNEXIONS/CONNEXION/SOURCE"> <xsl:if test="CONNEXION/SOURCE/@name] != BLOCK/@name]"> <xsl:attribute name="PointX"> <xsl:value-of select="puzzle/BLOCKS/BLOCK/@X+puzzle/CONNEXIONS/CONNEXION/SOURCE/@id"/> </xsl:attribute> </xsl:for-each> </space> </lSource> </program> </xsl:template> </xsl:stylesheet>
问题分析与修正代码
原代码问题点
- 路径错误:遍历
CONNEXION时,内部重复全量遍历所有SOURCE,未使用相对路径定位当前节点下的SOURCE - 匹配逻辑错误:
xsl:if条件写反,且存在语法错误(多余]符号) - 求和路径错误:直接选取所有
BLOCK的X值,未根据SOURCE的name匹配对应BLOCK - 输出方法错误:使用
method="html",但需要生成XML格式内容
修正后的XSLT代码
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output version="1.0" encoding="UTF-8" standalone="yes" indent="yes" method="xml"/> <xsl:strip-space elements="*"/> <!-- 定义键,通过name属性快速定位BLOCK元素 --> <xsl:key name="block-by-name" match="BLOCK" use="@name"/> <xsl:template match="/"> <program> <!-- 遍历每个CONNEXION节点 --> <xsl:for-each select="puzzle/CONNEXIONS/CONNEXION"> <lSource> <space> <!-- 获取当前CONNEXION下的SOURCE --> <xsl:variable name="current-source" select="SOURCE"/> <!-- 通过键匹配对应name的BLOCK --> <xsl:variable name="matched-block" select="key('block-by-name', $current-source/@name)"/> <!-- 计算求和值并生成pointX属性 --> <xsl:attribute name="pointX"> <xsl:value-of select="$matched-block/@X + $current-source/@id"/> </xsl:attribute> </space> </lSource> </xsl:for-each> </program> </xsl:template> </xsl:stylesheet>
代码说明
- 用
<xsl:key>建立BLOCK的name属性索引,提升匹配效率 - 遍历
CONNEXION时,通过相对路径获取当前节点下的SOURCE - 利用索引匹配对应
name的BLOCK,将两者属性值转为数值求和 - 输出方法改为
xml,确保生成标准XML格式
内容的提问来源于stack exchange,提问作者runy29
相关产品推荐
相关产品推荐

