0

I use Heat from Wix toolset to generate components for my installer but few of my installers are a Per-User and such i cannot use Heat's Autogenerate Guids. I can randomly generate a GUID but i don't want that because of components rules.

So I have an XML with list of files that should be included in the Installations in different structure than the generated one into which i have added static guids for each file. What i want to do is match the filename between my XML and generated XML and insert the GUID into my generated XML.

Here is a sample of the xml without any transformation:

<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Fragment>
        <DirectoryRef Id="Dir_Sample">
            <Directory Id="Folder1" Name="Folder1">
                <Component Id="NewTextFile0.txt" Guid="PUT-GUID-HERE">
                    <File Id="NewTextFile0.txt" KeyPath="yes" Source="$(var.sample)\Folder1\NewTextFile0.txt" />
                </Component>
            </Directory>
        </DirectoryRef>
    </Fragment>
    <Fragment>
        <ComponentGroup Id="CG_Sample">
            <ComponentRef Id="NewTextFile0.txt" />
        </ComponentGroup>
    </Fragment>
</Wix>

Here is my custom XML with GUIDs for each File:

<?xml version="1.0" encoding="utf-8"?>
<FileSystemList>
  <File Path="\Programs\Folder1\NewTextFile0.txt" Guid="52B62A6E-DD87-424A-8296-3AA00E74AEF8" />
</FileSystemList>

So i want Guid="PUT-GUID-HERE" be replaced with Guid="52B62A6E-DD87-424A-8296-3AA00E74AEF8" when the filename and preferably the parent folder matches on both XMLs.

I'm trying to understand XSL but all i'm able to achieve is hair loss. I and my remaining hair will appreciate any help.

Update: Matching between these two xml files should be performed on Source of the first file and Path of the second file.

Source="$(var.sample)\Folder1\NewTextFile0.txt" The file name (NewTextFile0.txt) and the parent folder (Folder1) together are unique in a project. The same goes for Path="\Programs\Folder1\NewTextFile0.txt" File name and parent folder being unique.

IlirB
  • 1,410
  • 14
  • 19
  • Do you use an XSLT 1.0 processor or an XSLT 2.0 processor (like Saxon 9)? With XSLT 2.0 it is rather simply to break up a string and to compare substring like that file path and it is simple to cross-reference between documents, with XSLT 1.0 it is more difficult to do for your sample as defining a key based on a substring is difficult to express. – Martin Honnen Apr 09 '14 at 09:20
  • Unfortunately it's version 1.0 – IlirB Apr 09 '14 at 09:33

1 Answers1

2

Try something like:

<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>

<!-- insert GUID -->    
<xsl:template match="wi:Component/@Guid">
    <xsl:variable name="path" select="concat(../../@Name, '\', ../@Id)" />
    <xsl:attribute name="Guid">
        <xsl:value-of select="document('FileList.xml')/FileSystemList/File[contains(@Path, $path)]/@Guid"/>
    </xsl:attribute>
</xsl:template>

</xsl:stylesheet>

Edit:

To base the match on the contents of Component/File/@Source, change the definition of the $pathvariable to:

<xsl:variable name="path" select="substring-after(../wi:File/@Source, ')')" />

This is assuming that anything in the Source attribute that comes after the first ")" is part of the path stored in the other file.

michael.hor257k
  • 113,275
  • 6
  • 33
  • 51
  • If i wanted the `path` to be matched against `Source` in `` how would i do that? – IlirB Apr 09 '14 at 13:19
  • @IlirB It depends on what the Source will contain. One example is not enough to establish a rule. Perhaps you should edit your question and clarify. Also, will there be only one File child of Component? – michael.hor257k Apr 09 '14 at 15:38
  • yes always One File : One Component. The reason i want the match to be performed on Source and not on the IDs is because that source will always have the exact and correct Filename while the IDs don't necessary contain the filename it can be random. – IlirB Apr 09 '14 at 18:37
  • @IlirB You haven't answered my first question: what exactly will Source contain that we can rely upon? In your example, there is `$(var.sample)` preceding a partial path. Will this exact string be **always** there? – michael.hor257k Apr 09 '14 at 19:36
  • @IlirB It's a simple yes/no question. Why is it so difficult to get an answer? – michael.hor257k Apr 09 '14 at 22:50
  • Yes assume it will always be there. – IlirB Apr 10 '14 at 00:13