如何在XSL中读取外部文档动态XPATH,匹配目标节点添加属性
解决方案
你需要通过XSLT的身份复制模板保留原有module.xml的所有结构,同时匹配每个元素时查询module_meta.xml的规则,为符合条件的节点追加effrg属性,以下是可直接运行的实现:
完整XSLT代码(XSLT 2.0及以上版本支持,主流XSLT处理器如Saxon均兼容)
<?xml version="1.0" encoding="UTF-8"?> <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()"/> <!-- 对当前元素查询是否有匹配的effect规则 --> <xsl:variable name="current-node" select="."/> <xsl:for-each select="document('module_meta.xml')/mdata/effectivity/effect"> <xsl:variable name="target-path" select="@path"/> <!-- 执行动态xpath查询,判断当前节点是否匹配路径 --> <xsl:if test="$current-node = xsl:evaluate($target-path)"> <xsl:attribute name="effrg" select="@effrg"/> </xsl:if> </xsl:for-each> </xsl:copy> </xsl:template> </xsl:stylesheet>
XSLT 1.0兼容方案(如果只能用XSLT 1.0处理器,可使用EXSLT的动态求值扩展)
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dyn="http://exslt.org/dynamic" extension-element-prefixes="dyn"> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> <xsl:variable name="current-node" select="."/> <xsl:for-each select="document('module_meta.xml')/mdata/effectivity/effect"> <xsl:if test="dyn:evaluate(concat('count($current-node intersect ', @path, ') = 1'))"> <xsl:attribute name="effrg"> <xsl:value-of select="@effrg"/> </xsl:attribute> </xsl:if> </xsl:for-each> </xsl:copy> </xsl:template> </xsl:stylesheet>
实现逻辑说明
- 核心用身份转换模板保证原有XML的所有内容、结构完全不变,只在匹配到规则的节点上追加属性
- 用
document('module_meta.xml')加载元数据文件,遍历所有effect规则 - 对每个规则执行动态XPATH查询,判断当前处理的节点是否匹配
path属性指定的路径 - 匹配成功则给当前节点追加
effrg属性,值为规则里的对应属性值
内容的提问来源于stack exchange,提问作者sboti8m
相关产品推荐
相关产品推荐

