Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Transform Heat generated .wxs with XSLT (add RegistryValue and edit some values)

Tags:

xml

xslt

wix

heat

This is my desired output:

<Component Id="C_SOMEFILE" Guid="some-guid-here">
    <File Id="File_SOMEFILE" Source="$(var.Source)\SOMEFILE" KeyPath="no" />
    <RegistryValue Root="HKCU" Key="Software\Product" Name="installed" Type="integer" Value="1" KeyPath="yes" />
</Component>

This is my XSLT file:

<xsl:stylesheet version="1.0" 
                            xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                            xmlns:wix="http://schemas.microsoft.com/wix/2006/wi"
                            xmlns="http://schemas.microsoft.com/wix/2006/wi"
                            exclude-result-prefixes="xsl wix">

<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />

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

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

<!--Set KeyPath to NO-->
<xsl:template match='wix:File[@Id]'>
    <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:attribute name="KeyPath">
            <xsl:text>no</xsl:text>
        </xsl:attribute>
    </xsl:copy>
</xsl:template>

<xsl:template match="wix:Component/wix:File">
    <xsl:copy-of select="." />
    <RegistryValue Root="HKCU" Key="Software\Product" Name="installed" Type="integer" Value="1" KeyPath="yes" />
</xsl:template>

<!--Give Compoentent ID prefix C_-->
<xsl:template match="wix:Component/@Id">
    <xsl:attribute name="{name()}">
        <xsl:value-of select="concat('C_', .)" />
    </xsl:attribute>
</xsl:template>

<!--Give Componentref ID prefix C_-->
<xsl:template match="wix:ComponentRef/@Id">
    <xsl:attribute name="{name()}">
        <xsl:value-of select="concat('C_', .)" />
    </xsl:attribute>
</xsl:template>

<!--Give Directory ID prefix Dir_-->
<xsl:template match="wix:Directory/@Id">
    <xsl:attribute name="{name()}">
        <xsl:value-of select="concat('Dir_', .)" />
    </xsl:attribute>
</xsl:template>

<!--Give File ID prefix File_-->
<xsl:template match="wix:File/@Id">
    <xsl:attribute name="{name()}">
        <xsl:value-of select="concat('File_', .)" />
    </xsl:attribute>
</xsl:template>

And this is my output using that XSL:

<Component Id="C_SOMEFILE" Guid="some-guid-here">
    <File Id="SOMEFILE" KeyPath="yes" Source="$(var.Source)\SOMEFILE" />
    <RegistryValue Root="HKCU" Key="Software\Product" Name="installed" Type="integer" Value="1" KeyPath="yes" />
</Component>

As soon as i activate

<xsl:template match="wix:Component/wix:File">
   <xsl:copy-of select="." />
   <RegistryValue Root="HKCU" Key="Software\Product" Name="installed" Type="integer" Value="1" KeyPath="yes" />
</xsl:template>

The File changes that are in XSL are not applied like add a prefix, change keypath to no, if i remove the one that adds the registry the file changes work like a charm!

What is it that i'm doing wrong?

Appreciate any help, thanks.

UPDATE: Here is original sample of XML without transform:

    <?xml version="1.0" encoding="utf-8"?>
    <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
       <Fragment>
          <DirectoryRef Id="Dir_Exentsions">
              <Directory Id="SOMEFILE" Name="SOMEFILE">
                 <Component Id="SOMEFILE" Guid="7D8FDF2D-CED9-4A08-A57E-96CD7FFA8E9A">
                    <File Id="SOMEFILE" KeyPath="yes" Source="$(var.Source)\SOMEFILE" />
                 </Component>          
              </Directory>
          </DirectoryRef>
       </Fragment>
     </Wix>
like image 335
IlirB Avatar asked Oct 18 '13 14:10

IlirB


People also ask

Which is used to transform XML data based on the XSLT script?

XSLT stands for Extensible Stylesheet Language Transformation. XSLT is used to transform XML document from one form to another form. XSLT uses Xpath to perform matching of nodes to perform these transformation .

How do you transform one XML to another XML document using XSLT transform?

The standard way to transform XML data into other formats is by Extensible Stylesheet Language Transformations (XSLT). You can use the built-in XSLTRANSFORM function to convert XML documents into HTML, plain text, or different XML schemas. XSLT uses stylesheets to convert XML into other data formats.


1 Answers

You say:

As soon as i activate

<xsl:template match="wix:Component/wix:File">
   <xsl:copy-of select="." />
   <RegistryValue Root="HKCU" Key="Software\Product" Name="installed" Type="integer" Value="1" KeyPath="yes" />
</xsl:template>

The File changes that are in XSL are not applied like add a prefix, change keypath to no, if i remove the one that adds the registry the file changes work like a charm!

By "activate", I assume that you mean add it to the XSLT file. When it is added to the rest of the transforms, you create an ambiguous rule match situation that should elicit a warning such as what Saxon would say:

 [xslt] : Error! Ambiguous rule match for /Wix/Fragment[1]/DirectoryRef[1]/Directory[1]/Component[1]/File[1]
 [xslt] Matches both "wix:Component/wix:File" on line 28 of file:/c:/gd/usr/kjh/proj/try/xslt/try.xsl
 [xslt] and "wix:File[@Id]" on line 19 of file:/c:/gd/usr/kjh/proj/try/xslt/try.xsl

Here's a resolution of the ambiguity:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:wix="http://schemas.microsoft.com/wix/2006/wi"
                xmlns="http://schemas.microsoft.com/wix/2006/wi"
                exclude-result-prefixes="xsl wix">

  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />

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

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

  <xsl:template match="wix:Component/wix:File[@Id]">
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:attribute name="KeyPath">
        <xsl:text>no</xsl:text>
      </xsl:attribute>
    </xsl:copy>
    <RegistryValue Root="HKCU" Key="Software\Product" Name="installed" Type="integer" Value="1" KeyPath="yes" />
  </xsl:template>

  <xsl:template match="wix:Component/wix:File[not(@Id)]">
    <!-- Placeholder for handling anything that should happen
         different for wix:File without @Id attribute.  -->
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
    </xsl:copy>
  </xsl:template>

  <!--Give Compoentent ID prefix C_-->
  <xsl:template match="wix:Component/@Id">
    <xsl:attribute name="{name()}">
      <xsl:value-of select="concat('C_', .)" />
    </xsl:attribute>
  </xsl:template>

  <!--Give Componentref ID prefix C_-->
  <xsl:template match="wix:ComponentRef/@Id">
    <xsl:attribute name="{name()}">
      <xsl:value-of select="concat('C_', .)" />
    </xsl:attribute>
  </xsl:template>

  <!--Give Directory ID prefix Dir_-->
  <xsl:template match="wix:Directory/@Id">
    <xsl:attribute name="{name()}">
      <xsl:value-of select="concat('Dir_', .)" />
    </xsl:attribute>
  </xsl:template>

  <!--Give File ID prefix File_-->
  <xsl:template match="wix:File/@Id">
    <xsl:attribute name="{name()}">
      <xsl:value-of select="concat('File_', .)" />
    </xsl:attribute>
  </xsl:template>
</xsl:stylesheet>

Which, when run on your input file, produces the desired output:

<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
   <Fragment>
      <DirectoryRef Id="Dir_Exentsions">
         <Directory Id="Dir_SOMEFILE" Name="SOMEFILE">
            <Component Id="C_SOMEFILE" Guid="7D8FDF2D-CED9-4A08-A57E-96CD7FFA8E9A">
               <File Id="File_SOMEFILE" KeyPath="no" Source="$(var.Source)\SOMEFILE"/>
               <RegistryValue Root="HKCU"
                              Key="Software\Product"
                              Name="installed"
                              Type="integer"
                              Value="1"
                              KeyPath="yes"/>
            </Component>
         </Directory>
      </DirectoryRef>
   </Fragment>
</Wix>
like image 193
kjhughes Avatar answered Dec 04 '22 04:12

kjhughes