Search code examples
xmlxsltwixtransformheat

WiX XSLT transform messing up my formatting


I'm trying to use a transform to add an attribute to a Component description. It is adding the attribute properly but messes up my XML formatting.

My goal is to add the attribute 'Permanent="yes" ' to the Component.

The XSLT is:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns="http://schemas.microsoft.com/wix/2006/wi"
    xmlns:wix="http://schemas.microsoft.com/wix/2006/wi">

    <xsl:template match="wix:Component">
        <xsl:copy>
            <xsl:apply-templates select="@*" />
            <xsl:attribute name="Permanent">
                <xsl:text>yes</xsl:text>
            </xsl:attribute>
            <xsl:apply-templates select="*" />
        </xsl:copy>
    </xsl:template>

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

    <xsl:template match="@* | text()">
        <xsl:copy />
    </xsl:template>

    <xsl:template match="/">
        <xsl:apply-templates />
    </xsl:template>

</xsl:stylesheet>

The .wxl file before transform looks like this:

<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Fragment>
        <DirectoryRef Id="SystemFolder">
            <Component Id="tdbgpp7.dll" Guid="{FA172CDA-D111-49BD-940F-F72EB8AC90DA}">
                <File Id="tdbgpp7.dll" KeyPath="yes" Source="$(var.OC2.WinSys32)\tdbgpp7.dll" />
            </Component>
        </DirectoryRef>
    </Fragment>
</Wix>

and after the transform looks like this:

<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Fragment>
        <DirectoryRef Id="SystemFolder">
            <Component Id="tdbgpp7.dll" Guid="{415E5416-AFE3-4658-8D74-489554345219}" Permanent="yes"><File Id="tdbgpp7.dll" KeyPath="yes" Source="$(var.OC2.WinSys32)\tdbgpp7.dll" /></Component>
        </DirectoryRef>
    </Fragment>
</Wix>

As you can see it is adding my attribute as expected but it loses some of the formatting. The code still works but loses readability. I know I must be missing something simple but so far it eludes me. I'm a noob to this transform stuff.


Solution

  • It's because in your template that matches wix:Component you do an <xsl:apply-templates select="*" />. This means you're only applying templates to elements so the text nodes (insignificant whitespace) inside of wix:Component are being stripped.

    I would suggest an identity transform and applying templates to node() in the wix:Component template...

    <xsl:stylesheet version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns="http://schemas.microsoft.com/wix/2006/wi"
      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="wix:Component">
        <xsl:copy>
          <xsl:apply-templates select="@*" />
          <xsl:attribute name="Permanent">
            <xsl:text>yes</xsl:text>
          </xsl:attribute>
          <xsl:apply-templates select="node()" />
        </xsl:copy>
      </xsl:template>
    
    </xsl:stylesheet>