Inserting line breaks into text using Rules

Q: How do I insert line breaks into a multi-line text box using rules?

First off, let’s introduce the concept of a multi-line text box properly. This functionality was added in InfoPath 2003 SP1. To enable it, insert a Text Box control, then on the Display tab, check “Paragraph breaks”. I usually also set the scrolling property to “Show scrollbars when necessary” and turn on “wrap text” which maps to the usual behavior for a multi-line text box. I also usually make the control bigger.

Without the “Paragraph breaks” property set, line breaks (CR, LF or CRLF) in the XML data are treated as any other whitespace and show up in a text box as spaces. The Enter key is ignored, and breaks are stripped on paste. With this property set the breaks are preserved and show in the control, and can be typed and pasted.

That’s good enough for round-tripping pre-existing breaks in the XML data and allowing user editing. And since you can party on the DOM as much as you want, inserting them via code is easy too – use whatever the escaping mechanism your language of choice provides – for example, in JScript you might use: oNode.text = "abcrndef"

How about rules? One of the rule actions available is to set a field’s value to the result of an expression. Behind the scenes, when the rule fires the expression is evaluated to return a string, and then the string is injected into the XML DOM as the node’s text. Specifying expressions like concat("abc", "
", "def") will result in a literal “&”, “#”, “x”, “A” and “;” appearing in the XML text. &-encoding is part of the file format, not of the DOM! The expression concat("abc", "n", "def") and other variants don’t work either – there’s no escaping mechanism in the evaluation used here.

So you need to figuratively copy/paste the line break from another source. Start off by literally doing a copy/paste of the following text into Notepad:

<?xml version="1.0" encoding="UTF-8"?>
<characters
cr="&#xD;"
lf="&#xA;"
crlf="&#xD;&#xA;"
/>

Save this as a file called “characters.xml”. Then in InfoPath go to Tools | Data Connections and click Add. Select Receive data, then XML Document. Browse to characters.xml then complete the wizard. When it asks “The selected file is not part of the form...add this file...?” click Yes. At this point we’ve just added a resource file to the template that gets loaded into a declaratively-accessible DOM - no code required.

Almost there - now let’s use it!

Add a Button control, open up the properties and click Rules. Add a Rule, and add an Action of the type “Set a field’s value”. For the field pick the text box’s field (e.g. field1). For the new value, use the formula builder and build the following expression:

concat(field1, @crlf, "Hello, world!")

The underlines indicate that this is a simplified version of the expression that conceals the full XPaths. Instead of typing it's easier to pick the fields using the “Insert Field or Group” button. Pick field1 from the main data source and pick @crlf from the “characters (Secondary)” data source (using the drop-down at the top of the dialog). Behind the scenes (as you can tell by clicking the “Edit XPath” button) this builds up the following expression:

concat(my:field1, xdXDocument:GetDOM("characters")/characters/@crlf, "Hello, world!")

Once you're done, click Preview, and try clicking the button a few times.

As a final note, InfoPath is agnostic about the whole CR vs. LF vs. CRLF debate. Any of the three is equally treated as a line break.