使用Heat.exe采集文件夹时忽略config子文件夹的问题排查
排查Heat.exe采集时排除config子文件夹的XSLT错误
问题描述
我尝试运行heat.exe采集一个包含3个子文件夹的目录,但希望忽略其中名为config的子文件夹。参考相关方案编写了XSLT样式表,但并未生效,恳请帮忙指出错误:
<xsl:stylesheet version="1.0" xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:wi="http://schemas.microsoft.com/wix/2006/wi" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl wi"> <xsl:output method="xml" indent="yes"/> <!-- default copy all --> <xsl:template match="@* | node()"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:template> <!-- Search directories for the components that will be removed. --> <xsl:key name="config-search" match="wi:Directory[@Name = 'config']" use="descendant::wi:Component/@Id" /> <!-- Remove directories. --> <xsl:template match="wi:Directory[@Name='config']" /> <!-- Remove componentsrefs referencing components in those directories. --> <xsl:template match="wi:ComponentRef[key('config-search', @Id)]" /> <!-- Get the right sourceDir for the files --> <xsl:template match="wi:File/@Source"> <xsl:attribute name="{name()}"> <xsl:variable name="sourceDirStart" select="substring-before(., '\')"/> <xsl:variable name="sourceDirEnd" select="substring-after(., '\')" /> <xsl:value-of select="concat($sourceDirStart, '\', $sourceDirEnd)" /> </xsl:attribute> </xsl:template> </xsl:stylesheet>
错误分析及修正方案
- Key定义逻辑倒置:原XSLT中
config-search的key匹配wi:Directory[@Name='config'],但用组件ID作为索引值,这会导致无法通过ComponentRef的ID反向关联到对应的config目录,匹配逻辑完全失效。 - ComponentRef匹配条件无效:因为key的定义错误,
wi:ComponentRef[key('config-search', @Id)]找不到任何需要删除的节点,所以无法移除对应组件引用。 - 冗余的Source属性处理模板:针对
wi:File/@Source的模板只是把属性值拆分后重新拼接,和原内容完全一致,无实际作用,还可能干扰正常节点处理。
修正后的XSLT代码
简化版(适合简单目录结构)
<xsl:stylesheet version="1.0" xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:wi="http://schemas.microsoft.com/wix/2006/wi" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl wi"> <xsl:output method="xml" indent="yes"/> <!-- 默认复制所有节点 --> <xsl:template match="@* | node()"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:template> <!-- 删除名为config的目录节点 --> <xsl:template match="wi:Directory[@Name='config']"/> <!-- 保留不属于config目录的组件引用 --> <xsl:template match="wi:ComponentRef"> <xsl:if test="not(//wi:Directory[@Name='config']//wi:Component[@Id=current()/@Id])"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:if> </xsl:template> </xsl:stylesheet>
高效版(适合复杂嵌套目录)
<xsl:stylesheet version="1.0" xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:wi="http://schemas.microsoft.com/wix/2006/wi" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl wi"> <xsl:output method="xml" indent="yes"/> <!-- 默认复制所有节点 --> <xsl:template match="@* | node()"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:template> <!-- 定义Key:用组件ID关联到所在的config目录 --> <xsl:key name="config-components" match="wi:Directory[@Name='config']//wi:Component" use="@Id"/> <!-- 删除config目录 --> <xsl:template match="wi:Directory[@Name='config']"/> <!-- 删除指向config目录组件的引用 --> <xsl:template match="wi:ComponentRef[key('config-components', @Id)]"/> </xsl:stylesheet>
内容的提问来源于stack exchange,提问作者brunofer42
相关产品推荐
相关产品推荐

