xf:include element includes external files in a form at compile time, during the evaluation of the
xsltforms.xsl stylesheet. It is thus similar in functionality to general entities in XML, or to the XInclude
It can be used to reduce duplication of code at multiple points in a form, to share code between forms, or just to move a complex part of a subform into a separate document to make the logic of the main form clearer and easier to follow.
xf:include element is empty. It carries just one attribute:
The value of the
src attribute is a URI reference (absolute or relative) pointing to an XML document to be included in the form.
Repeated code within a formEdit
Consider an XForm which accepts query data from a user, submits a query to a back end search engine, and displays the results to the user. To avoid overloading the user's browser and/or the network, we wish to send only a page's worth of results to the user at any one time, and allow the user to page through the results, so-and-so many results at a time.
The general outline of such a form might be something like this; we assume an instance named
query to hold the query string and the starting position within the results, and an instance named
results to hold the results.
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:xf="http://www.w3.org/2002/xforms" xmlns:ev="http://www.w3.org/2001/xml-events"> <head> ... </head> <body> <h2>Query tool</h2> ... controls for query string, submission ... <xf:group ref="instance('results')/self::result[.//hits]"> ... code for Back and Forward buttons ... <xf:repeat nodeset="self::test//hits/hit"> ... display one hit ... </xf:repeat> ... code for Back and Forward buttons ... </xf:group> </body> </html>
To reduce the need for scrolling up and down in the results page, we wish to have buttons for moving forward and back in the results both at the top of the results list and at the bottom. The code will be the same for both: first a Back button, which displays only if the current starting position is greater than 1:
<xf:group ref=".[instance('query')/startpos > 1]"> <xf:trigger> <xf:label>Back</xf:label> <xf:action ev:event="DOMActivate"> <xf:setvalue ref="instance('query')/startpos" value="instance('query')/startpos - instance('query')/pagesize "/> <xf:send submission="send-query"/> </xf:action> </xf:trigger> </xf:group>
Then a message indicating location in the results (e.g. "11 to 20 of 34", or "No results"):
<xf:group ref=".[.//hits/@n > 0][.//hit]"> <p>Results <xf:output ref=".//hit/@n"/> to <xf:output value=".//hit[last()]/@n"/> of <xf:output value="instance('results')//hits/@n"/> </p> </xf:group> <xf:group ref=".[.//hits/@n = 0]"> <p>No results.</p> </xf:group>
And finally a Forward button, which displays only if we are not currently displaying the last hit:
<xf:group ref=".[(instance('query')/startpos + count(.//hit)) <= (self::test/results/hits/@n)]"> <xf:trigger> <xf:label>Forward</xf:label> <xf:action ev:event="DOMActivate"> <xf:setvalue ref="instance('query')/startpos" value="instance('query')/startpos + instance('query')/pagesize"/> <xf:send submission="send-query"/> </xf:action> </xf:trigger> </xf:group>
Note that the forward and back buttons, and the current-location message, have no IDs that need to be unique; there is no problem including their text twice in the form. To make that happen, we must
- Make an XML document containing the Back button, the location message, and the Forward button. We wrap these three elements in an XHTML
divelement to give the XML a single root element, and call the result file "FBButtons.xhtml".
- In the appropriate locations in the main form, use the
xf:includeelement with the appropriate
srcvalue. If "FBButtons.xhtml" was placed in the same directory as the main form, we'll use
Known problems and issuesEdit
xf:includeelement works as specified in the main XForm, and recursively in documents loaded via
xf:include. In subforms, which are loaded later, it works in some browsers but not in others (including Webkit-based browsers). Cause of this discrepancy is the unwillingness of some browsers to evaluate the XSLT
- Browsers will enforce the same-origin policy, which means the absolute URI pointing to the XML document to be include will need to be on the same host as the form itself. [Tests and empirical confirmation of this claim would be desirable.]
For further informationEdit
- Alain Couthures to xsltforms-support list, 3 Jul 2016 explaining problems with use of
- Sample form showing use of
xf:includein main form and in dynamically loaded subform; the latter does not work.