1

我有一个 .wxs 文件,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Fragment>
        <Directory>
            <Directory Id="d1">
                <Component Id="c1" ...>
                    <File Id="f1" KeyPath="yes" ... />
                </Component>
                <Component Id="c2" ...>
                    <File Id="f2" KeyPath="yes" ... />
                </Component>
                <Component Id="c3" ...>
                    <File Id="f3" KeyPath="yes" ... />
                </Component>
            </Directory>
            <Directory>
                <Component>
                ...
            </Directory>
            ...
        </Directory>
    </Fragment>
    <Fragment>
        <ComponentGroup Id="cg1">
            <ComponentRef Id="c1" />
            <ComponentRef Id="c2" />
            <ComponentRef Id="c3" />
            ...
        </ComponentGroup>
    </Fragment>
</Wix>

我想“合并”上面的组件,即,我想将文件 f2、f3 移动到组件 c1 中,并想删除组件 c2、c3 以及 c2、c3 的组件引用。在我的实际源代码中,有更多目录,包括组件。我的目的是减少组件的数量,即对于任何模式,例如

<Directory>
    <Component>
        <File KeyPath="yes" />
    </Component>
    <Component>
        <File KeyPath="yes" />
    </Component>
    ...
    <Component>
        <File KeyPath="yes" />
    </Component>
</Directory>

我想将它们简化为一个组件(可能是第一个组件),包括许多文件,例如:

<Directory>
    <Component>
        <File KeyPath="yes" />
        <File />
        ...
        <File />
    </Component>
</Directory>

我知道不建议在一个组件中包含许多文件,但我想这样做以减少卸载时间。现在,我的安装程序需要很长时间才能卸载,我认为这是因为它的组件太多(大约 20,000 个)。

任何帮助,将不胜感激。谢谢你。

4

2 回答 2

1

我认为实现这一目标的最简单方法是使用following-sibling轴:

样式表

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:wi="http://schemas.microsoft.com/wix/2006/wi">
  <xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <!-- Identity transform -->
  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="wi:Directory">
    <xsl:copy>
      <!-- Only apply the first <Component> element -->
      <xsl:apply-templates select="wi:Component[1]"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="wi:Component[1]">
    <xsl:copy>
      <!-- Apply attributes -->
      <xsl:apply-templates select="@*"/>
      <!-- Apply the <File> element in this <Component> element -->
      <xsl:apply-templates select="wi:File"/>
      <!-- Apply the <File> elements in all following <Component> siblings -->
      <xsl:apply-templates select="following-sibling::wi:Component/wi:File"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

输入

<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
  <Fragment>
    <Directory Id="d1">
      <Component Id="c1">
        <File Id="f1" KeyPath="yes"/>
      </Component>
      <Component Id="c2">
        <File Id="f2" KeyPath="yes"/>
      </Component>
      <Component Id="c3">
        <File Id="f3" KeyPath="yes"/>
      </Component>
    </Directory>
  </Fragment>
  <Fragment>
    <ComponentGroup Id="cg1">
      <ComponentRef Id="c1"/>
      <ComponentRef Id="c2"/>
      <ComponentRef Id="c3"/>
    </ComponentGroup>
  </Fragment>
</Wix>

输出

<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
  <Fragment>
    <Directory>
      <Component Id="c1">
        <File Id="f1" KeyPath="yes"/>
        <File Id="f2" KeyPath="yes"/>
        <File Id="f3" KeyPath="yes"/>
      </Component>
    </Directory>
  </Fragment>
  <Fragment>
    <ComponentGroup Id="cg1">
      <ComponentRef Id="c1"/>
      <ComponentRef Id="c2"/>
      <ComponentRef Id="c3"/>
    </ComponentGroup>
  </Fragment>
</Wix>
于 2013-04-12T05:59:21.363 回答
0

这是我的回答。谢谢埃罗·赫勒纽斯。

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" 
            xmlns="http://schemas.microsoft.com/wix/2006/wi"
            xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
            xmlns:wix="http://schemas.microsoft.com/wix/2006/wi"
            exclude-result-prefixes="wix">
    <xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>

    <xsl:strip-space elements="*" />

    <xsl:key name="kRemoveComps" 
             match="wix:Directory/wix:Component[position()&gt;1]" use="@Id" />

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="wix:Directory">
        <xsl:copy>
            <xsl:apply-templates select="@*" />
            <xsl:apply-templates select="wix:Directory" />
            <xsl:apply-templates select="wix:Component[1]" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="wix:Component[1]">
        <xsl:copy>
            <!-- Attr. -->
            <xsl:apply-templates select="@*" />

            <!-- File in this Component -->
            <xsl:apply-templates select="wix:File" />

            <!-- Files in siblings -->
            <xsl:apply-templates select="../wix:Component[position()&gt;1]/wix:File" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="wix:Component[position()&gt;1]/wix:File">
        <xsl:copy>
            <!-- Removing KeyPath Attr. -->
            <xsl:apply-templates select="@*[not(name()='KeyPath')]|node()" />
        </xsl:copy>
    </xsl:template>

    <!-- Removing ComponentRef -->
    <xsl:template match="wix:ComponentRef[key('kRemoveComps', @Id)]" />
</xsl:stylesheet>
于 2013-04-12T08:35:14.433 回答