Wix 使用 Heat 工具收割后无法修改 Directoryref/Directory 元素的 Name 属性值
Cannot modify the Name attribute value of Directoryref/Directory element after Wix harvesting with Heat tool
在 WiX Toolset Heat 工具从源目录中收集组件后,它会生成一个 wxs 文件,例如以下内容。
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<DirectoryRef Id="TARGETDIR">
<Directory Id="dirGeneratedID1" Name="MySourceDirName">
<Component Id="cmpGeneratedID1" Guid="*">
<File Id="filGeneratedID1" KeyPath="yes" Source="$(var.SourceRootDir)\File1.dll" />
</Component>
<Component Id="cmpGeneratedID2" Guid="*">
<File Id="filGeneratedID2" KeyPath="yes" Source="$(var.SourceRootDir)\File2.dll" />
</Component>
<Directory Id="dirGeneratedID2" Name="MyNestedDirName">
<Component Id="cmpGeneratedID3" Guid="*">
<File Id="filGeneratedID3" KeyPath="yes" Source="$(var.SourceRootDir)\MyNestedDirName\File3.dll" />
</Component>
</Directory>
</Directory>
</DirectoryRef>
</Fragment>
</Wix>
我的任务是仅更改父目录元素的名称属性值。那就是将 /Wix/Fragment/DirectoryRef/Directory[@Name='MySourceDirName'] 元素的 Name 属性值从 'MySourceDirName' 更改为 'MY_RENAMED_SOURCE_DIR_NAME',因此我得到以下结果。
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<DirectoryRef Id="TARGETDIR">
<Directory Id="dirGeneratedID1" Name="MY_RENAMED_SOURCE_DIR_NAME">
<Component Id="cmpGeneratedID1" Guid="*">
<File Id="filGeneratedID1" KeyPath="yes" Source="$(var.SourceRootDir)\File1.dll" />
</Component>
<Component Id="cmpGeneratedID2" Guid="*">
<File Id="filGeneratedID2" KeyPath="yes" Source="$(var.SourceRootDir)\File2.dll" />
</Component>
<Directory Id="dirGeneratedID2" Name="MyNestedDirName">
<Component Id="cmpGeneratedID3" Guid="*">
<File Id="filGeneratedID3" KeyPath="yes" Source="$(var.SourceRootDir)\MyNestedDirName\File3.dll" />
</Component>
</Directory>
</Directory>
</DirectoryRef>
</Fragment>
</Wix>
由于生成wxs文件的是Heat工具,源目录名是'MySourceDirName',所以生成的Directory元素Name属性等于'MySourceDirName',后面需要进行XSL转换到我想要的新文件夹名称 'MY_RENAMED_SOURCE_DIR_NAME'.
我使用以下 XSLT,但它不起作用,我收到错误 "The DirectoryRef element contains an unexpected attribute 'Name'."
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:wix="http://schemas.microsoft.com/wix/2006/wi"
exclude-result-prefixes="wix">
<xsl:output omit-xml-declaration="no" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="/wix:Wix/wix:Fragment/wix:DirectoryRef/wix:Directory">
<xsl:attribute name="Name">
<xsl:choose>
<xsl:when test=". = 'MySourceDirName'">
<xsl:text>MY_RENAMED_SOURCE_DIR_NAME</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="." />
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet
XSLT 后生成的 wxs 文件变为错误且不完整的文件:
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<DirectoryRef Id="SciemetricDIR" Name="" />
</Fragment>
</Wix>
如果我更改我的XSLT并添加xsl:copy恢复内容如下(这里我只显示整个XSLT内容的影响规则)
<xsl:template match="/wix:Wix/wix:Fragment/wix:DirectoryRef/wix:Directory">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
<xsl:attribute name="Name">
<xsl:choose>
<xsl:when test=". = 'MySourceDirName'">
<xsl:text>MY_RENAMED_SOURCE_DIR_NAME</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="." />
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
</xsl:template>
然后我得到这个错误:"Error applying transform C:\path-to-my-transform-file\massageAfterHeatHarvesting.xsl to harvested WiX: Attribute and namespace nodes cannot be added to the parent element after a text, comment, pi, or sub-element node has already been added. MySoulutionName heat.exe 0 "
我的 XSLT 有什么问题?如果我清楚地以它下面的 Directory 子元素为目标,为什么它会触及 DirectoryRef 父元素?非常感谢任何支持。提前致谢。
XSLT 处理器遇到 Directory 元素,然后按照指定创建 Name 属性,仅此而已(它停止)。
尝试更改
<xsl:template match="/wix:Wix/wix:Fragment/wix:DirectoryRef/wix:Directory">
到
<xsl:template match="/wix:Wix/wix:Fragment/wix:DirectoryRef/wix:Directory/@Name">
事实上,将条件移动到匹配属性作为谓词会更好:
<xsl:template match="/wix:Wix/wix:Fragment/wix:DirectoryRef/wix:Directory/@Name[.='MySourceDirName']">
<xsl:attribute name="Name">MY_RENAMED_SOURCE_DIR_NAME</xsl:attribute>
</xsl:template>
在 WiX Toolset Heat 工具从源目录中收集组件后,它会生成一个 wxs 文件,例如以下内容。
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<DirectoryRef Id="TARGETDIR">
<Directory Id="dirGeneratedID1" Name="MySourceDirName">
<Component Id="cmpGeneratedID1" Guid="*">
<File Id="filGeneratedID1" KeyPath="yes" Source="$(var.SourceRootDir)\File1.dll" />
</Component>
<Component Id="cmpGeneratedID2" Guid="*">
<File Id="filGeneratedID2" KeyPath="yes" Source="$(var.SourceRootDir)\File2.dll" />
</Component>
<Directory Id="dirGeneratedID2" Name="MyNestedDirName">
<Component Id="cmpGeneratedID3" Guid="*">
<File Id="filGeneratedID3" KeyPath="yes" Source="$(var.SourceRootDir)\MyNestedDirName\File3.dll" />
</Component>
</Directory>
</Directory>
</DirectoryRef>
</Fragment>
</Wix>
我的任务是仅更改父目录元素的名称属性值。那就是将 /Wix/Fragment/DirectoryRef/Directory[@Name='MySourceDirName'] 元素的 Name 属性值从 'MySourceDirName' 更改为 'MY_RENAMED_SOURCE_DIR_NAME',因此我得到以下结果。
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<DirectoryRef Id="TARGETDIR">
<Directory Id="dirGeneratedID1" Name="MY_RENAMED_SOURCE_DIR_NAME">
<Component Id="cmpGeneratedID1" Guid="*">
<File Id="filGeneratedID1" KeyPath="yes" Source="$(var.SourceRootDir)\File1.dll" />
</Component>
<Component Id="cmpGeneratedID2" Guid="*">
<File Id="filGeneratedID2" KeyPath="yes" Source="$(var.SourceRootDir)\File2.dll" />
</Component>
<Directory Id="dirGeneratedID2" Name="MyNestedDirName">
<Component Id="cmpGeneratedID3" Guid="*">
<File Id="filGeneratedID3" KeyPath="yes" Source="$(var.SourceRootDir)\MyNestedDirName\File3.dll" />
</Component>
</Directory>
</Directory>
</DirectoryRef>
</Fragment>
</Wix>
由于生成wxs文件的是Heat工具,源目录名是'MySourceDirName',所以生成的Directory元素Name属性等于'MySourceDirName',后面需要进行XSL转换到我想要的新文件夹名称 'MY_RENAMED_SOURCE_DIR_NAME'.
我使用以下 XSLT,但它不起作用,我收到错误 "The DirectoryRef element contains an unexpected attribute 'Name'."
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:wix="http://schemas.microsoft.com/wix/2006/wi"
exclude-result-prefixes="wix">
<xsl:output omit-xml-declaration="no" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="/wix:Wix/wix:Fragment/wix:DirectoryRef/wix:Directory">
<xsl:attribute name="Name">
<xsl:choose>
<xsl:when test=". = 'MySourceDirName'">
<xsl:text>MY_RENAMED_SOURCE_DIR_NAME</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="." />
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet
XSLT 后生成的 wxs 文件变为错误且不完整的文件:
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<DirectoryRef Id="SciemetricDIR" Name="" />
</Fragment>
</Wix>
如果我更改我的XSLT并添加xsl:copy恢复内容如下(这里我只显示整个XSLT内容的影响规则)
<xsl:template match="/wix:Wix/wix:Fragment/wix:DirectoryRef/wix:Directory">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
<xsl:attribute name="Name">
<xsl:choose>
<xsl:when test=". = 'MySourceDirName'">
<xsl:text>MY_RENAMED_SOURCE_DIR_NAME</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="." />
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
</xsl:template>
然后我得到这个错误:"Error applying transform C:\path-to-my-transform-file\massageAfterHeatHarvesting.xsl to harvested WiX: Attribute and namespace nodes cannot be added to the parent element after a text, comment, pi, or sub-element node has already been added. MySoulutionName heat.exe 0 "
我的 XSLT 有什么问题?如果我清楚地以它下面的 Directory 子元素为目标,为什么它会触及 DirectoryRef 父元素?非常感谢任何支持。提前致谢。
XSLT 处理器遇到 Directory 元素,然后按照指定创建 Name 属性,仅此而已(它停止)。
尝试更改
<xsl:template match="/wix:Wix/wix:Fragment/wix:DirectoryRef/wix:Directory">
到
<xsl:template match="/wix:Wix/wix:Fragment/wix:DirectoryRef/wix:Directory/@Name">
事实上,将条件移动到匹配属性作为谓词会更好:
<xsl:template match="/wix:Wix/wix:Fragment/wix:DirectoryRef/wix:Directory/@Name[.='MySourceDirName']">
<xsl:attribute name="Name">MY_RENAMED_SOURCE_DIR_NAME</xsl:attribute>
</xsl:template>