使用XSLT将节点移入同级节点为子节点并添加属性(WiX V4)
解决WiX Toolset v4生成.wxs文件的自动修复问题
需求说明
通过调用heat.exe时应用XSLT样式表,自动修复生成的.wxs文件,需完成三项任务:
- 移除
RegistryValue节点 - 为
TypeLib节点添加Language="0"属性 - 将与
File同级的TypeLib节点移入File节点作为子节点
原始生成的XML
<!-- Starting XML --> <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> <Fragment> <DirectoryRef /> </Fragment> <Fragment> <ComponentGroup> <Component> <File /> <RegistryValue /> <TypeLib> <!-- Child Interface nodes. --> </TypeLib> </Component> </ComponentGroup> </Fragment> </Wix>
期望的目标XML
<!-- Desired XML --> <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> <Fragment> <DirectoryRef /> </Fragment> <Fragment> <ComponentGroup> <Component> <File> <TypeLib Language="0"> <!-- Child Interface nodes. --> </TypeLib> </File> </Component> </ComponentGroup> </Fragment> </Wix>
现有未完成需求的XSLT样式表
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:wix="http://wixtoolset.org/schemas/v4/wxs"> <xsl:output method="xml" indent="yes" /> <xsl:template match="@*|node()" name="identity"> <xsl:copy> <xsl:apply-templates select="@*|node()" /> </xsl:copy> </xsl:template> <!-- Remove the RegistryValue attribute. --> <xsl:template match="wix:RegistryValue" /> <!-- Add the missing Language="0" attribute to the TypeLib component. --> <xsl:template match="wix:TypeLib" name="add-language"> <xsl:copy> <xsl:apply-templates select="@*"/> <xsl:attribute name="Language">0</xsl:attribute> <xsl:apply-templates select="node()" /> </xsl:copy> </xsl:template> <!-- Select the file node and make the typelib node a child. --> <xsl:template match="wix:File"> <xsl:copy> <xsl:apply-templates select="@*" /> <xsl:call-template name="add-language" /> <!--<xsl:copy-of select="following-sibling::wix:TypeLib[1]" />--> <xsl:apply-templates select="node()" /> </xsl:copy> </xsl:template> <xsl:template match="wix:TypeLib[preceding-sibling::*[1][self::wix:File]]" /> </xsl:stylesheet>
修正后的完整XSLT样式表
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:wix="http://wixtoolset.org/schemas/v4/wxs"> <xsl:output method="xml" indent="yes" /> <!-- 身份模板:默认复制所有节点和属性 --> <xsl:template match="@*|node()" name="identity"> <xsl:copy> <xsl:apply-templates select="@*|node()" /> </xsl:copy> </xsl:template> <!-- 移除RegistryValue节点 --> <xsl:template match="wix:RegistryValue" /> <!-- 为TypeLib节点添加Language="0"属性 --> <xsl:template match="wix:TypeLib" name="add-language"> <xsl:copy> <xsl:apply-templates select="@*"/> <xsl:attribute name="Language">0</xsl:attribute> <xsl:apply-templates select="node()" /> </xsl:copy> </xsl:template> <!-- 处理File节点:将同级的TypeLib移入作为子节点,并应用属性添加模板 --> <xsl:template match="wix:File"> <xsl:copy> <xsl:apply-templates select="@*" /> <!-- 复制File自身的子节点 --> <xsl:apply-templates select="node()" /> <!-- 选取当前File后续同级的第一个TypeLib,调用add-language模板处理 --> <xsl:apply-templates select="following-sibling::wix:TypeLib[1]" mode="move" /> </xsl:copy> </xsl:template> <!-- 匹配需要移动的TypeLib,调用add-language模板 --> <xsl:template match="wix:TypeLib" mode="move"> <xsl:call-template name="add-language" /> </xsl:template> <!-- 移除原位置的TypeLib节点 --> <xsl:template match="wix:TypeLib[preceding-sibling::wix:File]" /> </xsl:stylesheet>
关键修改说明
- 调整File节点模板:在复制File节点时,通过
following-sibling::wix:TypeLib[1]选取其后续的第一个TypeLib节点,使用mode="move"调用专门的处理模板,避免和默认TypeLib模板冲突。 - 新增move模式模板:专门处理需要移动的TypeLib,调用已有的
add-language模板完成属性添加,实现逻辑复用。 - 简化TypeLib移除模板:直接匹配所有位于File节点之后的TypeLib节点,移除原位置的节点,避免重复输出。
内容的提问来源于stack exchange,提问作者Kira
相关产品推荐
相关产品推荐

