0

I am working on wix, and i need to install a windows service. As part of that, i need to set KeyPath="yes" only on the service executable. I am using HarvestDirectory task that produces an output like so:

<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Fragment>
        <DirectoryRef Id="INSTALLFOLDER">
            <Component Id="cmp4BB0346D363B37CAFD72ED8BBAFE3DC3" Guid="*">
                <File Id="fil1F519C40510B9CE08968AFE1141C5124" KeyPath="yes" Source="$(var.My.Awesome.Product.TargetDir)\My.Awesome.Product.dll" />
            </Component>
        <!-- Many more here -->
        </DirectoryRef>
    </Fragment>
    <Fragment>
        <ComponentGroup Id="ProductFiles">
            <ComponentRef Id="cmp4BB0346D363B37CAFD72ED8BBAFE3DC3" />
            <!-- Many more here -->
        </ComponentGroup>
    </Fragment>
</Wix>

What i want to do is write an XSLT that will change KeyPath to "no" for all files except when Source = $(var.My.Awesome.Product.TargetDir)\My.Awesome.Product.exe

E.g. sample output would be:

<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Fragment>
        <DirectoryRef Id="INSTALLFOLDER">
            <Component Id="cmp4BB0346D363B37CAFD72ED8BBAFE3DC3" Guid="*">
           <!-- note the 'no' in the KeyPath here -->
                <File Id="fil1F519C40510B9CE08968AFE1141C5124" KeyPath="no" Source="$(var.My.Awesome.Product.TargetDir)\My.Awesome.Product.dll" />
            </Component>
             <Component Id="cmp5BB0346D363B37CAFD72ED8BBAFE3DC3" Guid="*">
                <File Id="fil2F519C40510B9CE08968AFE1141C5124" KeyPath="yes" Source="$(var.My.Awesome.Product.TargetDir)\My.Awesome.Product.exe" />
            </Component>
        <!-- Many more here -->
        </DirectoryRef>
    </Fragment>
    <Fragment>
        <ComponentGroup Id="ProductFiles">
            <ComponentRef Id="cmp4BB0346D363B37CAFD72ED8BBAFE3DC3" />
            <ComponentRef Id="cmp5BB0346D363B37CAFD72ED8BBAFE3DC3" />
            <!-- Many more here -->
        </ComponentGroup>
    </Fragment>
</Wix>

I have got the following XSLT that replaces 'yes' with 'no' on all KeyPath attributes:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:wix="http://schemas.microsoft.com/wix/2006/wi">
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="@KeyPath">
        <xsl:attribute name="KeyPath">
            <xsl:value-of select="'no'"/>
        </xsl:attribute>
    </xsl:template>
</xsl:stylesheet>

I tried manipulating the match in the second template using parent, ancestor and simple node with attributes File[@KeyPath='yes'] selectors to no avail.

zx485
  • 28,498
  • 28
  • 50
  • 59
zaitsman
  • 8,984
  • 6
  • 47
  • 79
  • `File[@KeyPath='yes']` will not select anything when `File` is in a **namespace** - see: https://stackoverflow.com/questions/34758492/xslt-transform-doesnt-work-until-i-remove-root-node/34762628#34762628 – michael.hor257k Jul 19 '17 at 15:03
  • @michael.hor257k sure, but how can i replace all but one? – zaitsman Jul 19 '17 at 15:08

1 Answers1

2

What i want to do is write an XSLT that will change KeyPath to "no" for all files except when Source = $(var.My.Awesome.Product.TargetDir)\My.Awesome.Product.exe

That part would be written as:

<xsl:template match="wix:File[not(@Source='$(var.My.Awesome.Product.TargetDir)\My.Awesome.Product.exe')]/@KeyPath">
    <xsl:attribute name="KeyPath">
        <xsl:value-of select="'no'"/>
    </xsl:attribute>
</xsl:template>

Note that this does not do what you said at the beginning of your question:

i need to set KeyPath="yes" only on the service executable.

I am not sure what that means and I am even more confused by the fact that your input does not match your output.

michael.hor257k
  • 113,275
  • 6
  • 33
  • 51