Highlight a phrase and click this icon to search it on Swyx-Forum    Highlight a phrase and click this icon to search it within the Swyx Knowledgebase    Highlight a phrase and click this icon to search it using Goolge    Highlight a phrase and click this icon to search it using Wikipedia

Highlight a phrase and click this icon to search it on Swyx-Forum    Highlight a phrase and click this icon to search it within the Swyx Knowledgebase    Highlight a phrase and click this icon to search it using Goolge    Highlight a phrase and click this icon to search it using Wikipedia

List of Blogs
Search Blogs

Blog Archive

Most recent blog entries

 

Most recent blog entries

 

Okt9

Written by:Martin
09.10.2008 19:24 

Warning: Technical content ahead. XML and programming know-how required :-)

Today a colleague mentioned an issue with our setup build process for SwyxWare v7.0. We have some xml configuration files which need to be adapted depending on the product language or OEM version. These files have settings like this:

Warning: Technical content ahead. XML and programming know-how required :-)

Today a colleague mentioned an issue with our setup build process for SwyxWare v7.0. We have some xml configuration files which need to be adapted depending on the product language or OEM version. These files have settings like this:

<configuration>

  <applicationSettings>

    <MyApp>

      <setting name="companyName">Swyx</setting>

      <setting name="culture">en-US</setting>

    </MyApp>

  </appSettings>

</configuration>

Noticed “Swyx” and “en-US”? These are the settings to change. The localized or OEM-specific values to be used are already defined in special localization xml files used by the Windows Installer XML Toolset we’re using for the build. Here’s an example:

<WixLocalization>

    <String Id='companyName'>T-Com</String>

    <String Id='assemblyCulture'>de-DE</String>

</WixLocalization>

There are usually several of these string table files.

And there are different xml files with different elements to patch. Therefore the process has to be flexible. The idea was to write a program which uses the above string table files plus a definition which elements in which config files to change. The definition file looks like this:

<PatchInstruction>

  <File Name="a.config">

    <Node XPath="/configuration/applicationSettings/MyApp/setting[@name='culture']/value"

          Value="assemblyCulture" />

    <Node XPath="/configuration/applicationSettings/MyApp/setting[@name='OEMName']/value"

          Value="companyName" />

  </File>

  <File Name="b.config">

    <Node XPath="/configuration/applicationSettings/AnotherApp/setting[@name='culture']/value"

          Value="assemblyCulture" />

    <Node XPath="/configuration/applicationSettings/AnotherApp/setting[@name='Manufacturer']/value"

          Value="companyName" />

  </File>

</PatchInstruction>

It defines that two nodes in file a.config and two in b.config are to be changed. The XPath attribute defines the location in the xml file to change and the Value attribute specifies the string table entry to use as new value.

Looks complicated? It isn’t. I suggested using a Windows Powershell script to solve this. Here’s my first attempt:

  1. param([string]$patchinstructionfile,$wxlfiles)  
  2.  
  3. # read string table  
  4. $stringtable = @{}  
  5.  
  6. foreach ($filename in $wxlfiles)  
  7. {  
  8.    $f = [xml](get-content (Resolve-Path $filename))  
  9.    foreach ($string in $f.WixLocalization.String)  
  10.    {  
  11.       $StringTable.add($string.id,$string.innertext)  
  12.    }  
  13. }  
  14.  
  15. # read patch instructions  
  16. $patchinstructions = [xml](get-content $patchinstructionfile)  
  17.  
  18. # patch files  
  19. foreach ($file in $patchInstructions.PatchInstruction.File)  
  20. {  
  21.    # read file  
  22.    $filepath = Resolve-Path $file.name  
  23.    $f = [xml](get-content $filepath)  
  24.  
  25.    # patch   
  26.    foreach ($node in $file.node)  
  27.    {  
  28.       $f.selectSingleNode($node.xpath).innertext = $stringtable.($node.value)   
  29.    }  
  30.    # save  
  31.    $f.save($filepath)  

It could be somewhat shorter when using the PowerShell pipe (|) operator. And some error handling wouldn’t hurt, too. But it works. You probably need to have a good understanding on how to solve this in another language like C++, VB or C# to see how easy and powerful (sic!) this language is.

 

 

Tags:

 


Your name:
Your email:
(Optional) Email used only to show Gravatar.
Title:
Comment:
Security Code
Enter the code shown above in the box below
Add Comment  Cancel 
Blog Help
Sponsors