From MSI to WiX, Part 25 – Installable Items – Updating XML files using XmlFile


To use XmlFile element we need to:



  • Add  reference to WixUtilExtension extension.

  • Add util namespace to <Wix> element:

<?xml version=1.0 encoding=UTF-8?>


<Wix xmlns=http://schemas.microsoft.com/wix/2006/wi


     xmlns:util=http://schemas.microsoft.com/wix/UtilExtension>


Here is what we can do with existing XML file using XmlFile element:



  • Set the value of an attribute

  • Set the text value of an element

  • Create new element

  • Create new attribute

  • Delete the text value of an element

  • Delete the attribute

    Preparing an installation


Here is the original content of XML file we are going to update (app.config):


<?xml version=1.0 encoding=utf-8 ?>


<configuration>


  <UserName></UserName>


  <Parameters>-DeleteAll</Parameters>


  <EmptyElement>123</EmptyElement>


  <appSettings>


    <add key=NoValue value=“” />


    <add key=NoValue2 value=“” />


    <add key=ExtraAttribute value=MyValue extra=“” />


  </appSettings>


  <BulkSet1>


    <add key=key1 value=“” />


    <add key=key2 value=“” />


    <add key=key3 value=“” />


  </BulkSet1>


  <BulkSet2>


    <add key=key1 value=“” />


    <add key=key2 value=“” />


    <add key=key3 value=“” />


  </BulkSet2>


</configuration>





This is the wxs file to install app.config file:


<?xml version=1.0 encoding=UTF-8?>


<Wix xmlns=http://schemas.microsoft.com/wix/2006/wi


     xmlns:util=http://schemas.microsoft.com/wix/UtilExtension>


    <Product Id=78c586b0-3f59-405f-9f2e-a0370b7be99b


           Name=XmlFileUpdate


           Language=1033


           Version=1.0.0.0


           Manufacturer=XmlFileUpdate


           UpgradeCode=1f711338-7bcc-4cc3-bcd9-1a47bf128409>


        <Package InstallerVersion=200 Compressed=yes />


 


        <Media Id=1 Cabinet=media1.cab EmbedCab=yes />


 


        <Directory Id=TARGETDIR Name=SourceDir>


            <Directory Id=ProgramFilesFolder>


                <Directory Id=INSTALLLOCATION Name=XmlFileUpdate>


                    <Component Id=ProductComponent


                     Guid=03ade8d5-cdab-4a50-a950-e16cebb8bbae>


            <File Id=AppConfig


                  DiskId=1


                  Name=app.config


                  Source=app.config


                  Vital=yes


                  KeyPath=yes />


          </Component>


                </Directory>


            </Directory>


        </Directory>


 


        <Feature Id=ProductFeature Title=XmlFileUpdate Level=1>


            <ComponentRef Id=ProductComponent />


        </Feature>


    </Product>


</Wix>


    Set attribute or element value 


Now, let’s set the value of “NoValue” element (<add> element with key attrubute set to “NoValue) to the value of INSTALLLOCATION property.  In other words, from this:


<add key=NoValue value=“” />


we want to get this result:


<add key=NoValue value=C:\Program Files\XmlFileUpdate\/>


All we need to do is to add to component XmlFile element:


<Component Id=ProductComponent


           Guid=03ade8d5-cdab-4a50-a950-e16cebb8bbae>


  <File Id=AppConfig


        DiskId=1


        Name=app.config


        Source=app.config


        Vital=yes


        KeyPath=yes />


 


  <util:XmlFile Id=SetKey1


                Action=setValue


                ElementPath=//appSettings/add[\[]@key=’NoValue'[\]]/@value


                Value=[INSTALLLOCATION]


                File=[#AppConfig]


                SelectionLanguage=XPath


                Sequence=1 />


 


</Component>


 


The following attributes need to be set:





  • Action attribute is set to setValue.


  • ElementPath attribute contains an XPath or XSLTPattern expression pointing to attribute which value we want to set.


  • Value attribute contains new formatted value of the attribute.


  • File attribute points to a file where changes will be made.  This value is also formatted and that is why we can use [#FileId] notation instead of providing full path to XML file.


  • Sequence attribute defines the order in which modification will be made.  This value matters only when we need to create new element with attribute.  In this case we need to ensure that element is created before attempting to create an attribute.  As a good practice, always set this value in order in which you prefer items to be updated.

Alternative version will be to use XPath expression, pointing to an element and use Name attribute to set which attribute’s value to change:


<util:XmlFile Id=SetKey2


              Action=setValue


              ElementPath=//appSettings/add[\[]@key=’NoValue2′[\]]


              Value=[INSTALLLOCATION]


              Name=value


              File=[#AppConfig]


              SelectionLanguage=XPath


              Sequence=2 />



To set the value of existing attribute to an empty string we need to just omit the Value attribute:


<util:XmlFile Id=SetKey3


              Action=setValue


              ElementPath=//appSettings/add[\[]@key=’ExtraAttribute'[\]]


              Name=value


              File=[#AppConfig]


              SelectionLanguage=XPath


              Sequence=3 />



Tip:  To target an element, provide XPath (or XSLPattern) expression pointing to an element and do not specify Name attribute. To target an attribute – either provide XPath expression pointing to element and set the name of an attribute in the Name attribute, or provide XPath expression pointing to attribute and do not specify Name attribute.


Based on the tip above, here is how we set the text value of an element:


<util:XmlFile Id=SetKey4


              Action=setValue


              ElementPath=//UserName


              Value=[%USERNAME]


              File=[#AppConfig]


              SelectionLanguage=XPath


              Sequence=4 />



And this is how to set element’s text value to empty string:


<util:XmlFile Id=SetKey5


              Action=setValue


              ElementPath=//Parameters


              File=[#AppConfig]


              SelectionLanguage=XPath


              Sequence=5 />



    Delete attribute or element’ text value


Here is how we can delete an attribute:


<util:XmlFile Id=DeleteKey6


              Action=deleteValue


              ElementPath=//appSettings/add[\[]@key=’ExtraAttribute'[\]]


              Name=extra


              File=[#AppConfig]


              SelectionLanguage=XPath


              Sequence=6 />



Here Action attribute is set to deleteValue.  The meaning of all other attributes is the same as in previous examples.  ElementPath attribute points to a node and Name attribute contains the name of the attribibute to be deleted.


There is inconsistency in the way how XmlFile element works if we will omit the Name attribute.  Instead of removing element it removes text value of the element, just like Sequence=”5″ in example above.  So, here is how to remove text value of an element:


<util:XmlFile Id=DeleteKey7


              Action=deleteValue


              ElementPath=//EmptyElement


              File=[#AppConfig]


              SelectionLanguage=XPath


              Sequence=7 />


     Create element and attribute


To create a new element, we need to set Action attribute to createElement:


<util:XmlFile Id=CreateElement1


              Action=createElement


              ElementPath=//configuration


              Name=NewElement1


              File=[#AppConfig]


              SelectionLanguage=XPath


              Sequence=8 />



To create a new element and set its text value we need to add Value attribute:


<util:XmlFile Id=CreateElement2


              Action=createElement


              ElementPath=//configuration


              Name=NewElement2


              Value=New Value


              File=[#AppConfig]


              SelectionLanguage=XPath


              Sequence=9 />



Creating element with attributes is little bit more complicated.  First, we need to create an element and then create attributes.  That is where the value of Sequence attribute is very important.  Let’s create new add element in appSettings section:


<util:XmlFile Id=CreateElement3


              Action=createElement


              ElementPath=//appSettings


              Name=add


              File=[#AppConfig]


              Sequence=10 />


<util:XmlFile Id=CreateAttribute1


              Action=setValue


              ElementPath=//appSettings/add[\[]not(@key)[\]]


              Name=key


              Value=NewParameter


              File=[#AppConfig]


              Sequence=11 />


<util:XmlFile Id=CreateAttribute2


              Action=setValue


              ElementPath=//appSettings/add[\[]@key=’NewParameter'[\]]


              Name=value


              Value=NewValue


              File=[#AppConfig]


              Sequence=12 />



First, we create a new add element (Sequence 10). Second, we create a key attribute.  XPath expression is searching for an add element which does not have a key attribute (Sequence 11).  Last XmlFile element creates a value attribute (Sequence 12).


    Bulk set


XmlFile element supports bulk update.


For example, from this:


<BulkSet1>


  <add key=key1 value=“”/>


  <add key=key2 value=“”/>


  <add key=key3 value=“”/>


</BulkSet1>



we want to get this:


<BulkSet1>


  <add key=key1 value=C:\Program Files\XmlFileUpdate\/>


  <add key=key2 value=C:\Program Files\XmlFileUpdate\/>


  <add key=key3 value=C:\Program Files\XmlFileUpdate\/>


</BulkSet1>



Basically, we want to set every value attribute to the value of INSTALLLOCATION property.  Using regular setValue as a value for Action attribute:


<util:XmlFile Id=BulkSetKey1


              Action=setValue


              ElementPath=//configuration/BulkSet1/add


              Name=value


              Value=[INSTALLLOCATION]


              File=[#AppConfig]


              SelectionLanguage=XPath


              Sequence=13 />



creates the following result:


<BulkSet1>


  <add key=key1 value=C:\Program Files\XmlFileUpdate\/>


  <add key=key2 value=“”/>


  <add key=key3 value=“”/>


</BulkSet1>



To fix this, we need to set Action attribute to bulkSetValue:


<util:XmlFile Id=BulkSetKey2


              Action=bulkSetValue


              ElementPath=//configuration/BulkSet2/add


              Name=value


              Value=[INSTALLLOCATION]


              File=[#AppConfig]


              SelectionLanguage=XPath


              Sequence=14 />



Here is the result:


<BulkSet2>


  <add key=key1 value=C:\Program Files\XmlFileUpdate\/>


  <add key=key2 value=C:\Program Files\XmlFileUpdate\/>


  <add key=key3 value=C:\Program Files\XmlFileUpdate\/>


</BulkSet2>



 


This is pretty much all we can do with XmlFile element.  Source code for post is in attachment.

XmlFileUpdate.zip

Comments (9)

  1. amx3000 says:

    > Here is what we can do with existing XML file using XmlFile element:

    >

    >    * Set the value of an attribute

    >    * Set the text value of an element

    >    * Create new element

    >    * Create new attribute

    >    * Delete the text value of an element

    >    * Delete the attribute

    And how can I *read* a text value from element?

  2. kemal dincer says:

    how to got custom config data from UserInterface dialog?

  3. Andy Clark says:

    Is it possible to merge a value for example if the existing value is "test" could I change it to "test,test2" ?

  4. Rami says:

    Thank you, Alex.

    This post helped me alot! 🙂

  5. pagi says:

    how to set the value for

    books

    book  name="value";

    book  name="value";

    book name="value"

    books

  6. krishna says:

    Hi,

    All !!

    I have successfully created setup for MVC Web Application using wix toolset, it is working fine under Default Web Site.

    I have no issue under Default Web Site, but can any one help me if  i want to create new website with some other port no rather than creating website under Default website in IIS..

    i.e.:  IIS>> Sites>> Default Web site >>My MVC App    is working fine.

    Problem in below structure::

    i.e.:  IIS>> Sites>> My MVC App  

    Thanks in Advance!!

  7. Utpal Patel says:

    Thanks a lot!!

  8. Tim Mayert says:

    Excuse a newbie question here, but with the ElementPath where can I get more information on what is actually suppose to be written there/acceptable correct values? I am an install developer using WiX 3.7 and was given the task of updating a .config file during install. They want 2 entries added – one a ServiceInfo with value of Server Address and one entry ClientMode that can be one of 3 optional values. This was all the information I was given and therefore I do not know what ElementPath should be or the acceptable values that I need to set it to. So can I get more information on ElementPath? Thanks for any help.

  9. TimM says:

    Newbie question here, but how do you determine what the ElementPath should be for any given entry? Have never used this functionality before and have just been given the task of adding 2 entries to an application .config file and only information given was for key ServerInfo = [SERVER_ADDRESS] and key ClientMode=[CLIENT_MODE].

    So would like to figure out how to get this ElementPath so that I can get it working. Thanks for Any help.