Usability - Productivity - Business - The web - Singapore & Twins

Summer diet for your Notes Forms

The title I wanted to give this post was Spring clean your notes forms, but then it did get delayed....
One hallmark of Notes applications is their durability. It is quite common to find applications being in use, that root back into R3 or R4. Quite a number of these applications still look like that too. That's the flip-site of not needing to rip-and-replace. Sometimes you also will find, that older forms load slower and behave odd at times. Before you start beautifying your applications, it is a good idea to do some spring cleaning. To do so I use Domino's DXL to extract a form in XML, filter it through a XSLT transformation and reimport that into the database.
The LotusScript code is very straight forward, has been well covered on developer works and the help file and looks like this:

Set importer = session.CreateDXLImporter(stream, dbCopy)
importer.ReplicaRequiredForReplaceOrUpdate = False
importer.DesignImportOption = DXLIMPORTOPTION_CREATE
Call importer.Process<

The "meat" is in the transformation. The XSLT file consist of 4 principal sections that contain templates. In section 1 we find the start of the output including the wrapper and calls to various templates. In section 2 design elements are filtered out, in section 3 design elements are tweaked, finally in section 4 the remaining DXL is copied 1:1 to the resulting document; . The sequence of the sections is not relevant, since XSLT uses priorities not sequence to determine what element to apply. What are the elements you can or should spring clean:

  • In DXL I found NotesItems between the </body> and the </form> tag. Removing this from the form makes the form smaller, load faster without any change in behavior.
  • Font information is encoded inside the <run> tag. The <run> tag is similar to HTML's <span>. When you designed and re-designed forms over and over, there will be <run> tags that only contain a font change, but not actual any characters. Filtering that out lightens the form - Filter out all paragraph formats and/or fonts to be able to apply a new look & feel more easily
  • Convert access controlled sections into subforms (to work in the web)
  • Remove (all) LotusScript code and move it to libraries (see an upcoming SnTT post on "Classical Forms" about that).

Let us look at some code....

Section 1 starts the whole stylesheet.

    <xsl:template match="/">
            <!-- We get the attribute from the first element which might be a database or a form -->
            <xsl:attribute name="replicaid">
                <!-- Get the replicaid -->
                <xsl:value-of select="/child::node()[1]/@replicaid"/>
            <xsl:attribute name="version">
                <!-- Get the designer version -->
                <xsl:value-of select="/child::node()[1]/@version"/>
            <!-- get all other attributes -->
            <xsl:apply-templates select="@*"/>
            <!-- apply the templates for regular forms -->
            <!-- apply the templates for the additional generation like LotusScript and Suforms -->
            <xsl:apply-templates mode="genLS" select="/d:form/d:globals"/>
            <xsl:apply-templates mode="genSub" select="//d:section[@accessfieldkind]"/>
            <xsl:apply-templates mode="genRead" select="//d:section[@accessfieldkind]"/>


Section 2 features match clauses with no content inside the template. It is closed in the opening tag using />. If a tag should be filtered, but its content be processed you just have the <xsl:apply-templates /> statement as the only content.

    <!-- Section 2: Filter out elements we do not want or need -->
    <!--  Filter out  change of font if there is not content inside-->
    <xsl:template match="d:run[node()[last()=1][self::d:font]]"/>

    <!-- Filter out the note infoand update info -->
    <xsl:template match="d:noteinfo"/>
    <xsl:template match="d:updatedby"/>
    <xsl:template match="d:wassignedby"/>

    <!-- remove a form background color -->
    <xsl:template match="d:form/@bgcolor" />

    <!-- Filter out items after the body tag -->
    <xsl:template match="d:form/d:item"/>

    <!-- Filter out attributes -->
    <xsl:template match="@replicaid"/>
    <xsl:template match="@version"/>
    <xsl:template match="@milestonebuild"/>

    <!-- remove left margin values from pardefs, so they use the default dangerous!!!! -->
    <xsl:template match="@leftmargin"/>
    <xsl:template match="@firstlineleftmargin"/>

    <!-- Filter font information we don't want -->
    <xsl:template match="d:font/@truetype"/>
    <xsl:template match="d:font/@name"/>
    <xsl:template match="d:font/@pitch"/>
    <xsl:template match="d:font/@familyid"/>

There is actually much more in the stylesheet, so check the sample stylesheet in the download section.

Section 3 features some tweaks to existing elements:

<xsl:template match="d:richtext">
            <!-- Add a hidden field for Debug information and update all hidden fields to use that formula instead of hide='read edit copy preview previewedit' -->
            <xsl:if test="count(//d:field[@name='isNotDebug'])=0">
                <pardef hide="read edit print copy preview previewedit">
                    <xsl:attribute name="id">
                        <xsl:value-of select="$pardefcount"/>
                    <xsl:attribute name="def">
                        <xsl:value-of select="$pardefcount"/>
                        <font color="red"/>
                        <field type="number" kind="computedfordisplay" name="isNotDebug">
                            <code event="defaultvalue">

    <!-- Replace all paragraph definition where hide='read edit copy preview previewedit' with hidewhen isNotDebug -->
        match="d:pardef[@hide='read edit copy preview previewedit' or @hide='read edit print copy preview previewedit']">
            <xsl:attribute name="id">
                <xsl:value-of select="@id"/>
            <code event="hidewhen">

    <!-- change the ugly fucsia font to light gray -->
    <xsl:template match="d:font/@color[node()='fucisa']">
        <xsl:attribute name="color">gray</xsl:attribute>

    <!-- standardize on 9pt for 8 and 9 pt font sizes -->
    <xsl:template match="d:font/@size['8pt' or '9pt']">
        <xsl:attribute name="size">9pt</xsl:attribute>

    <!-- remove font sizes for the rest -->
    <xsl:template match="d:font/@size[not ('8pt' or '9pt')]"/>

    <!-- more radical approach : remove all font information -->
    <!-- xsl:template match="d:font" / -->

Section 4 has been used in many other examples before. It leverages on the fact, that the match="*" has the lowest priority and only is applied if there is no other suitable template:

    <!-- Section 4 : Copy any element 1:1 from source to target -->
    <xsl:template match="*">
        <xsl:variable name="curTagname" select="name()"/>
        <xsl:element name="{$curTagname}">
            <!-- Walk through the attributes -->
            <xsl:apply-templates select="@*"/>
            <!-- process the children -->

    <xsl:template match="@*">
        <xsl:variable name="curAttName" select="name()"/>
        <xsl:attribute name="{$curAttName}">
            <xsl:value-of select="."/>

Before you send back that DXL into a datbase you could scrub it further by removing pardef sections that have identical definitions. However this would require a second run with another stylesheet or some good old LotusScript code.

As usual YMMV

Posted by on 27 April 2007 | Comments (1) | categories: Show-N-Tell Thursday


  1. posted by Thomas Bahn on Monday 30 April 2007 AD:
    Didn't you get some problems with this DXL-turn-around? Layout regions? (Shared) Action? Additional or missing line breaks?

    Which version of Notes do you use?