xmlxslt

Transforming Wix XML with XSLT in MSBuild to Add RegistryValue


I am trying to transform an XML file using XSLT in MSBuild's TransformXml task. My goal is to modify a Wix XML file by adding a <RegistryValue> element inside each <Component> and remove KeyPath="yes" from <File>.

Input XML:

<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Fragment>
        <DirectoryRef Id="INSTALLFOLDER">
            <Component Id="cmp3E8A66A51C067CB532D96BDB574D5B62" Guid="{7DF9EBF3-A8FF-4A1D-BEEB-6A84A31A5484}">
                <File Id="fil2934E863A1FB7CCB3F2B4AE5D7638C21" KeyPath="yes" Source="test.json" />
            </Component>
            <Component Id="cmpAC81A7A6F463ADCB651789415E02A5EB" Guid="{67BA41FF-FF45-436B-9DF3-C311B061485B}">
                <File Id="fil9E171FDD3F525EDE194757D2A95D1311" KeyPath="yes" Source="test2.json" />
            </Component>
        </DirectoryRef>
    </Fragment>
</Wix>

Expected Output:

<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Fragment>
        <DirectoryRef Id="INSTALLFOLDER">
            <Component Id="cmp3E8A66A51C067CB532D96BDB574D5B62" Guid="{7DF9EBF3-A8FF-4A1D-BEEB-6A84A31A5484}">
                <RegistryValue Root="HKCU" Key="Key" Name="Installed" Type="integer" Value="1" KeyPath="yes"/>
                <File Id="fil2934E863A1FB7CCB3F2B4AE5D7638C21" Source="test.json" />
            </Component>
            <Component Id="cmpAC81A7A6F463ADCB651789415E02A5EB" Guid="{67BA41FF-FF45-436B-9DF3-C311B061485B}">
                <RegistryValue Root="HKCU" Key="Key" Name="Installed" Type="integer" Value="1" KeyPath="yes"/>
                <File Id="fil9E171FDD3F525EDE194757D2A95D1311" Source="test2.json" />
            </Component>
        </DirectoryRef>
    </Fragment>
</Wix>

What I've Tried:

I am using MSBuild's TransformXml task, but I need help writing the XSLT to achieve this transformation. I need an XSLT that will:

  1. Copy everything from the original XML.
  2. Insert a <RegistryValue> before the <File> element inside each <Component>.

Could someone help me with the correct XSLT for this transformation?


Solution

  • I believe the correct answer is:

    XSLT 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:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    
    <!-- identity transform -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="wix:Component">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <RegistryValue xmlns="http://schemas.microsoft.com/wix/2006/wi" Root="HKCU" Key="Key" Name="Installed" Type="integer" Value="1" KeyPath="yes"/>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>
        
    <xsl:template match="wix:File/@KeyPath"/>
    
    </xsl:stylesheet>