Tuesday, March 11, 2014

XSLT: Structuring Data in Attributes or in Child Elements

We are free to select tags to our liking, so are to build an XML structure, whether it is element-based, where there is almost no attributes in the XML tree (see the following exmample) or attribute-based (converted by XSLT code to be shown below).

<?xml version="1.0" encoding="UTF-8"?>
<catalog>
 <cd>
  <title>Empire Burlesque</title>
  <artist>Bob Dylan</artist>
  <country>USA</country>
  <company>Columbia</company>
  <price>10.90</price>
  <year>1985</year>
 </cd>
 <cd>
  <title>Hide your heart</title>
  <artist>Bonnie Tyler</artist>
  <country>UK</country>
  <company>CBS Records</company>
  <price>9.90</price>
  <year>1988</year>
 </cd>
 <cd>
  <title>Greatest Hits</title>
  <artist>Dolly Parton</artist>
  <country>USA</country>
  <company>RCA</company>
  <price>9.90</price>
  <year>1982</year>
 </cd>
 <cd>
  <title>Still got the blues</title>
  <artist>Gary Moore</artist>
  <country>UK</country>
  <company>Virgin records</company>
  <price>10.20</price>
  <year>1990</year>
 </cd>
 <cd>
  <title>Eros</title>
  <artist>Eros Ramazzotti</artist>
  <country>EU</country>
  <company>BMG</company>
  <price>9.90</price>
  <year>1997</year>
 </cd>
 <cd>
  <title>One night only</title>
  <artist>Bee Gees</artist>
  <country>UK</country>
  <company>Polydor</company>
  <price>10.90</price>
  <year>1998</year>
 </cd>
 <cd>
  <title>Sylvias Mother</title>
  <artist>Dr.Hook</artist>
  <country>UK</country>
  <company>CBS</company>
  <price>8.10</price>
  <year>1973</year>
 </cd>
 <cd>
  <title>Maggie May</title>
  <artist>Rod Stewart</artist>
  <country>UK</country>
  <company>Pickwick</company>
  <price>8.50</price>
  <year>1990</year>
 </cd>
 <cd>
  <title>Romanza</title>
  <artist>Andrea Bocelli</artist>
  <country>EU</country>
  <company>Polydor</company>
  <price>10.80</price>
  <year>1996</year>
 </cd>
 <cd>
  <title>When a man loves a woman</title>
  <artist>Percy Sledge</artist>
  <country>USA</country>
  <company>Atlantic</company>
  <price>8.70</price>
  <year>1987</year>
 </cd>
 <cd>
  <title>Black angel</title>
  <artist>Savage Rose</artist>
  <country>EU</country>
  <company>Mega</company>
  <price>10.90</price>
  <year>1995</year>
 </cd>
 <cd>
  <title>1999 Grammy Nominees</title>
  <artist>Many</artist>
  <country>USA</country>
  <company>Grammy</company>
  <price>10.20</price>
  <year>1999</year>
 </cd>
 <cd>
  <title>For the good times</title>
  <artist>Kenny Rogers</artist>
  <country>UK</country>
  <company>Mucik Master</company>
  <price>8.70</price>
  <year>1995</year>
 </cd>
 <cd>
  <title>Big Willie style</title>
  <artist>Will Smith</artist>
  <country>USA</country>
  <company>Columbia</company>
  <price>9.90</price>
  <year>1997</year>
 </cd>
 <cd>
  <title>Tupelo Honey</title>
  <artist>Van Morrison</artist>
  <country>UK</country>
  <company>Polydor</company>
  <price>8.20</price>
  <year>1971</year>
 </cd>
 <cd>
  <title>Soulsville</title>
  <artist>Jorn Hoel</artist>
  <country>Norway</country>
  <company>WEA</company>
  <price>7.90</price>
  <year>1996</year>
 </cd>
 <cd>
  <title>The very best of</title>
  <artist>Cat Stevens</artist>
  <country>UK</country>
  <company>Island</company>
  <price>8.90</price>
  <year>1990</year>
 </cd>
 <cd>
  <title>Stop</title>
  <artist>Sam Brown</artist>
  <country>UK</country>
  <company>A and M</company>
  <price>8.90</price>
  <year>1988</year>
 </cd>
 <cd>
  <title>Bridge of Spies</title>
  <artist>T`Pau</artist>
  <country>UK</country>
  <company>Siren</company>
  <price>7.90</price>
  <year>1987</year>
 </cd>
 <cd>
  <title>Private Dancer</title>
  <artist>Tina Turner</artist>
  <country>UK</country>
  <company>Capitol</company>
  <price>8.90</price>
  <year>1983</year>
 </cd>
 <cd>
  <title>Midt om natten</title>
  <artist>Kim Larsen</artist>
  <country>EU</country>
  <company>Medley</company>
  <price>7.80</price>
  <year>1983</year>
 </cd>
 <cd>
  <title>Pavarotti Gala Concert</title>
  <artist>Luciano Pavarotti</artist>
  <country>UK</country>
  <company>DECCA</company>
  <price>9.90</price>
  <year>1991</year>
 </cd>
 <cd>
  <title>The dock of the bay</title>
  <artist>Otis Redding</artist>
  <country>USA</country>
  <company>Atlantic</company>
  <price>7.90</price>
  <year>1987</year>
 </cd>
 <cd>
  <title>Picture book</title>
  <artist>Simply Red</artist>
  <country>EU</country>
  <company>Elektra</company>
  <price>7.20</price>
  <year>1985</year>
 </cd>
 <cd>
  <title>Red</title>
  <artist>The Communards</artist>
  <country>UK</country>
  <company>London</company>
  <price>7.80</price>
  <year>1987</year>
 </cd>
 <cd>
  <title>Unchain my heart</title>
  <artist>Joe Cocker</artist>
  <country>USA</country>
  <company>EMI</company>
  <price>8.20</price>
  <year>1987</year>
 </cd>
</catalog>

With the help of XSLT, we can easily transform element-based data into attribute-based data. Several points to notice in the XSLT code:

  • child selector child::
  • element name name()
  • element text text()
  • dynamic attribute name {name()}
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <catalog>
        <xsl:for-each select="catalog/cd">
            <cd>
                <xsl:for-each select="child::*">
                    <xsl:attribute name="{name(.)}">
                        <xsl:value-of select="text()"/>
                    </xsl:attribute>
                </xsl:for-each>
            </cd>
        </xsl:for-each>
        </catalog>
    </xsl:template>
</xsl:stylesheet>

Result: the attribute-based data.

<catalog>
    <cd title="Empire Burlesque" artist="Bob Dylan" country="USA" company="Columbia" price="10.90" year="1985" />
    <cd title="Hide your heart" artist="Bonnie Tyler" country="UK" company="CBS Records" price="9.90" year="1988" />
    <cd title="Greatest Hits" artist="Dolly Parton" country="USA" company="RCA" price="9.90" year="1982" />
    <cd title="Still got the blues" artist="Gary Moore" country="UK" company="Virgin records" price="10.20" year="1990" />
    <cd title="Eros" artist="Eros Ramazzotti" country="EU" company="BMG" price="9.90" year="1997" />
    <cd title="One night only" artist="Bee Gees" country="UK" company="Polydor" price="10.90" year="1998" />
    <cd title="Sylvias Mother" artist="Dr.Hook" country="UK" company="CBS" price="8.10" year="1973" />
    <cd title="Maggie May" artist="Rod Stewart" country="UK" company="Pickwick" price="8.50" year="1990" />
    <cd title="Romanza" artist="Andrea Bocelli" country="EU" company="Polydor" price="10.80" year="1996" />
    <cd title="When a man loves a woman" artist="Percy Sledge" country="USA" company="Atlantic" price="8.70" year="1987" />
    <cd title="Black angel" artist="Savage Rose" country="EU" company="Mega" price="10.90" year="1995" />
    <cd title="1999 Grammy Nominees" artist="Many" country="USA" company="Grammy" price="10.20" year="1999" />
    <cd title="For the good times" artist="Kenny Rogers" country="UK" company="Mucik Master" price="8.70" year="1995" />
    <cd title="Big Willie style" artist="Will Smith" country="USA" company="Columbia" price="9.90" year="1997" />
    <cd title="Tupelo Honey" artist="Van Morrison" country="UK" company="Polydor" price="8.20" year="1971" />
    <cd title="Soulsville" artist="Jorn Hoel" country="Norway" company="WEA" price="7.90" year="1996" />
    <cd title="The very best of" artist="Cat Stevens" country="UK" company="Island" price="8.90" year="1990" />
    <cd title="Stop" artist="Sam Brown" country="UK" company="A and M" price="8.90" year="1988" />
    <cd title="Bridge of Spies" artist="T`Pau" country="UK" company="Siren" price="7.90" year="1987" />
    <cd title="Private Dancer" artist="Tina Turner" country="UK" company="Capitol" price="8.90" year="1983" />
    <cd title="Midt om natten" artist="Kim Larsen" country="EU" company="Medley" price="7.80" year="1983" />
    <cd title="Pavarotti Gala Concert" artist="Luciano Pavarotti" country="UK" company="DECCA" price="9.90" year="1991" />
    <cd title="The dock of the bay" artist="Otis Redding" country="USA" company="Atlantic" price="7.90" year="1987" />
    <cd title="Picture book" artist="Simply Red" country="EU" company="Elektra" price="7.20" year="1985" />
    <cd title="Red" artist="The Communards" country="UK" company="London" price="7.80" year="1987" />
    <cd title="Unchain my heart" artist="Joe Cocker" country="USA" company="EMI" price="8.20" year="1987" />
</catalog>

Friday, March 7, 2014

VBScript: Dynamically Create GUIDs

Function CreateGUID()
 Set TypeLib = CreateObject("Scriptlet.TypeLib") 
 myGuid = CStr(TypeLib.Guid)
 CreateGUID = Left(myGuid, Len(myGuid)-2)
 Set TypeLib = Nothing
End Function

Wednesday, February 12, 2014

Windows Installer: Migrating From InstallShield to WiX

Notice: I've prepared my scripts into this repository github: IS2WiX [5].

Preparation

Installing WiX Toolset will get you all the tools to compile all XML files in your WiX project. It will also install templates to Visual Studio and VS does automatically configure compilation options for you.

We need programming knowledge from XSLT/XPATH to operate on XML files, also some VB.NET knowledge to write customized custom actions.

Here is a list of all related tools and languages.

  • WiX Toolset[1], documentation
  • Visual Studio 2012
  • Microsoft SDK (Orca.exe, Wilogutl.exe etc.[2])
  • XSLT, XPath, XML
  • VB.NET Custom Actions
  • InstallShield, Help file
  • Your InstallShield project file and Internet Explorer[3]

The Idea

WiX and InstallShield are tools to make .msi packages, they all base on Microsoft Windows Installer technology. They all use .xml files to represent their project, where .xml is either handcrafted or auto-generated from parameters set from a graphic interface. So to build a bridge between the two, we seek XSLT for help.

Example

Your Binary table shall look similar to this.
<table name="Binary">
 <col key="yes" def="s72">Name</col>
 <col def="V0">Data</col>
 <col def="S255">ISBuildSourcePath</col>
 <row><td>ISLockPermissions.dll</td><td/><td>[ISProductFolder]\redist\Language Independent\i386\ISLockPermissions.dll</td></row>
 <row><td>ISSCHRPL.DLL</td><td/><td>[ISProductFolder]\redist\language independent\i386\isschrpl.dll</td></row>
 <row><td>ISSetup.dll</td><td/><td>[ISProductFolder]\redist\language independent\i386\ISSetup.dll</td></row>
 ...
</table>

Let's write a stylesheet to convert the above table to WiX format,

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" />
    <xsl:template match="/">
        <xsl:for-each select="/table/row">
            <Binary>
                <xsl:attribute name="Id">
                  <xsl:value-of select="td[1]" /></xsl:attribute>
                <xsl:attribute name="SourceFile">
                  <xsl:value-of select="td[3]" /></xsl:attribute>
            </Binary>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

The output shall look like,

<Binary Id="ISLockPermissions.dll" SourceFile="[ISProductFolder]\redist\Language Independent\i386\ISLockPermissions.dll" />
<Binary Id="ISSCHRPL.DLL" SourceFile="[ISProductFolder]\redist\language independent\i386\isschrpl.dll" />
<Binary Id="ISSetup.dll" SourceFile="[ISProductFolder]\redist\language independent\i386\ISSetup.dll" />

View the InstallShield Project

Your project is composed of tables. With the help of stylesheet written in is.xsl[4], you could have a direct view of all these tables.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<?xml-stylesheet type="text/xsl" href="is.xsl" ?>

From InstallShiled MSI tables to WiX

One can search help files provided by WiX to study how it is really mapped. The following is an incomplete list collected while I was working on a migration project.

IS/MSIWiX ElementParent
ActionTextProgressTextUI
AdminExecuteSequenceAdminExecuteSequenceFragment
AdminUISequenceAdminUISequenceFragment
AdvtExecuteSequenceAdvertiseExecuteSequenceProduct
AppSearchDirectorySearchProperty
BinaryBinaryFragment
CheckBoxControl Type="CheckBox" CheckBoxValue=""Dialog
ComponentComponentFragment, Directory
ControlControlDialog
ControlConditionConditionControl
ControlEventPublishUI
CreateFolderCreateFolderDirectory
CustomActionCustomActionFragment
DialogDialogUI
DirectoryDirectoryDirectoryref, Fragment
DrLocatorDirectorySearchProperty
ErrorErrorUI
EventMappingSubscribeControl
FeatureFeatureFeatureGroup, Fragment
FeatureComponentsFeatureRef, ComponentRef, ComponentGroupRefFragment
FileFileComponent
FontFile TrueType=yesComponent
ISStringStringWixLocalization
IconIconShortcut
InstallExecuteSequenceInstallExecuteSequenceProduct
InstallUISequenceInstallUISequenceUI
PropertyPropertyProduct
RadioButtonRadioButton, RadioButtonGroupControl
RegistryRegistryComponent
ServiceControlServiceControlComponent
ServiceInstallServiceInstallComponent
ShortcutShortcutComponent
TextStyleTextStyleUI
UITextUITextUI
UpgradeUpgrade, UpgradeVersionProduct

Footnote

  1. WiX Toolset
  2. Windows Installer Development Tools
  3. Chrome will have problems viewing an .xml file referencing another .xsl file locally due to the cross-origin security issue.
  4. By default, the stylesheet file should be at C:\Program Files (x86)\InstallShield\2011\Support\is.xsl
  5. Github: IS2WiX

Myriad

Visitors