InfoPath 2007 has a lot of new great features including dynamic buttons where a button text can be specified via xpath. Unfortunately, such features are not Designer-compatible with InfoPath 2003, that is, you will be able to edit your forms alright but it won’t be possible to design them – the views containing them will be marked as "protected".
One possible workaround is to use the xd:preserve blocks in your XSL – this works great at the cost of having to do this manually and the inability to edit the contents of those in Designer. My recommendation is to avoid using those excessively and to keep their contents as simple as possible because otherwise maintenance becomes hell. However, it’s good solution when you absolutely need to use constructs Designer does not support.
The way xd:preserve works is via a special mode that applies to templates. Suppose you have the following piece of XSL:
<span class="xdTextBox" xd:CtrlId="CTRL1" style="WIDTH: 130px">
<xsl:value-of select="my:field1"/>
</span>
In order to wrap it in xd:preserve, you move the entire XSL into a separate template:
<xsl:template match="my:field1" mode="xd:preserve">
<span class="xdTextBox" xd:CtrlId="CTRL1" style="WIDTH: 130px">
<xsl:value-of select="."/>
</span>
</xsl:template>
Notice how the value-of’s select attribute changed to "." from "my:field1". Now, all you need to do is to replace the original XSL with the call to the newly created template:
<xsl:apply-templates select=" my:field1" mode="xd:preserve"/>
Although this approach works great for bound controls, it doesn’t for buttons for the simple reason that they do not have an xpath to bind to. Although you could pick some random value in the main data source it would be hacky. Also, if you have more buttons than nodes in your data source, you won’t be able to wrap them all in xd:preserve.
The solution to this problem is to introduce a simple secondary data source with an entry for each unbound control you’d like to wrap. It’s best done with an XML file such as this:
<buttons>
<button1/>
<button2/>
</buttons>
Now all you need to do is to use xpaths into this Secondary DOM. Assuming it’s called ButtonsPaths, the following ApplyTemplates will do the trick:
<xsl:if test="function-available('xdXDocument:GetDOM')">
<xsl:apply-templates select="xdXDocument:GetDOM("ButtonsPaths")/buttons/button1" mode="xd:preserve"/>
</xsl:if>
At this point, simply move your XSL/HTML into the button1 template and you’re done:
<xsl:template match="button1" mode="xd:preserve">
Your HTML goes here
</xsl:template>