使用XSLT样式表移除与外部文件内容匹配的XML元素
解决方案
XSLT 1.0 实现方案(兼容现有工具链)
XSLT 1.0 不允许在key的match属性、模板匹配表达式中直接引用外部文档变量,因此调整实现逻辑,通过显式判断文件名是否在排除列表来过滤节点,完整样式表如下:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:wix="http://schemas.microsoft.com/wix/2006/wi" xmlns="http://schemas.microsoft.com/wix/2006/wi"> <!-- 身份转换:默认复制所有节点和属性 --> <xsl:template match="@*|*"> <xsl:copy> <xsl:apply-templates select="@*" /> <xsl:apply-templates select="*" /> </xsl:copy> </xsl:template> <xsl:output method="xml" indent="yes" encoding="utf-8" /> <!-- 读取外部排除文件列表 --> <xsl:variable name="excludedFiles" select="document('filelist.xml')/Files/File"/> <!-- 过滤需要删除的Component节点 --> <xsl:template match="wix:Component"> <xsl:variable name="fileName" select="substring-after(wix:File/@Source, '\')"/> <!-- 不在预定义排除列表、也不在外部文件排除列表的节点才保留 --> <xsl:if test="not($fileName = 'FileA' or $excludedFiles[. = $fileName])"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:if> </xsl:template> <!-- 过滤对应Component已被删除的ComponentRef节点 --> <xsl:template match="wix:ComponentRef"> <xsl:variable name="refId" select="@Id"/> <!-- 只有对应Component还存在的引用才保留 --> <xsl:if test="//wix:Component[@Id = $refId]"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:if> </xsl:template> </xsl:stylesheet>
说明
- 用
substring-after(wix:File/@Source, '\')提取文件名,替代之前硬编码长度的写法,适配不同长度的文件名 - 预定义排除的文件(如
FileA)可以直接在test判断中追加,不需要额外修改逻辑 - 处理
ComponentRef时通过判断关联的Component是否存在来自动过滤,不需要手动维护Id映射
XSLT 2.0 可选方案
如果后续可以升级到XSLT 2.0,实现会更简洁,直接用序列存储排除文件名即可:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:wix="http://schemas.microsoft.com/wix/2006/wi" xmlns="http://schemas.microsoft.com/wix/2006/wi" exclude-result-prefixes="#all"> <xsl:mode on-no-match="shallow-copy"/> <xsl:output method="xml" indent="yes" encoding="utf-8"/> <!-- 合并预定义排除文件和外部文件排除列表 --> <xsl:variable name="excludedFiles" select="('FileA', document('filelist.xml')/Files/File/string())"/> <!-- 直接匹配要删除的Component --> <xsl:template match="wix:Component[substring-after(wix:File/@Source, '\') = $excludedFiles]"/> <!-- 直接匹配要删除的ComponentRef --> <xsl:template match="wix:ComponentRef[@Id = //wix:Component[substring-after(wix:File/@Source, '\') = $excludedFiles]/@Id]"/> </xsl:stylesheet>
内容的提问来源于stack exchange,提问作者Michael Stoll
相关产品推荐
相关产品推荐

