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:
- param([string]$patchinstructionfile,$wxlfiles)
-
-
- $stringtable = @{}
-
- foreach ($filename in $wxlfiles)
- {
- $f = [xml](get-content (Resolve-Path $filename))
- foreach ($string in $f.WixLocalization.String)
- {
- $StringTable.add($string.id,$string.innertext)
- }
- }
-
-
- $patchinstructions = [xml](get-content $patchinstructionfile)
-
-
- foreach ($file in $patchInstructions.PatchInstruction.File)
- {
-
- $filepath = Resolve-Path $file.name
- $f = [xml](get-content $filepath)
-
-
- foreach ($node in $file.node)
- {
- $f.selectSingleNode($node.xpath).innertext = $stringtable.($node.value)
- }
-
- $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.