XPath Functions

FIT provides a number of XPath functions that are not part of XPath 1.0, but should prove useful when working with FIT.

Reference

content()

The content XPath function is a convenient function to access contents from inside the flow. However, as an XPath function you may use it in expressions outside the flow, too.

<flow>
  <default-request />
  <if test="content()/html/head/title = 'Thank you'">
    ...
  </if>
  ...
</flow>

When called without parameter, the function returns the main content DOM from fit://request/content.

The following XPath expressions are equivalent:

  • content()/html/head/title
  • content('')/html/head/title
  • fit-document('fit://request/content')/html/head/title
  • in XSLT you may use the standard function document('fit://request/content')/html/head/title

Be aware that fit://request/content and fit://request/content/main are not the same thing! While the first starts as a copy of the latter, flow actions may alter fit://request/content throughout the request. fit://request/content/main holds the plain text response body and usually remains unchanged. Thus, content() and content('main') are not necessarily equivalent.

Optionally, a content ID can be passed to read data from fit://request/content/<ID>:

  • content('side')/some/data

The content function returns a node-set that contains the document node of the DOM in fit://request/content/<ID>. When the content does not exist, the node-set will be empty.

ends-with()

boolean ends-with(string haystack, string needle)

The function ends-with returns true if the first argument string ends with the second argument string, and otherwise returns false.

Examples

  • ends-with("foo", "oo") returns true
  • ends-with(request/url, ".json") could be used to identify JSON resources

fit-document()

The fit-document function accepts exactly one argument that is converted to a string. The argument must be an URI pointing to a fit://-URL, otherwise an empty result is returned and an error will be raised. The resource referenced by that URL is retrieved and the data resulting from the retrieval action is parsed as an XML document and a tree is constructed in accordance with the data model.

If the content pointed to by the URI can be retrieved and parsed, the fit-document function returns a DOMNodeList containing the document node at the root of the resulting tree. When attempting to access non-existent content, the DOMNodeList will be empty.

The fit-document function is similar to the XSLT document function.

Example

<flow>
  <dump if="fit-document('fit://site/conf/local.xml')/conf/dump" />
</flow>

fit-log()

boolean fit-log(string message)

The XPath function fit-log writes the given message into the fit_engine.log. Unless invalid parameters are supplied, the fit-log function always returns true(). Therefore, it can easily be used in the if attribute of all flow actions, as shown in the example below.

Example

<flow>
  <default-request />
  ...
  <xslt if="fit-log('Process my XSLT')" src="XSLT.xsl" />
  ...
</flow>

Example fit_engine.log log line:

2015-12-01 11:12:13+0200 VmaNmn8AAAEAAB3Gy08AAABA myProject Process my XSLT

fit-serialize()

string fit-serialize(string|number|boolean|node-set argument [, boolean pretty-print = true()])

The XPath function fit-serialize generates a storable and human readable representation of the given node-set. For example, you could use this function to obtain a string representation of an XML DOM and log it via the fit-log() function for debugging.

If the type of the argument is scalar (string, number or boolean), the argument is cast to string and output as is.

If the pretty-print parameter is set to true() (which is the default), the fit-serialize function will try to generate nicely formatted output for a node-set. If set to false() the argument is output as is.

An empty node-set results in an empty string.

Examples

<flow>
  <default-request />
  ...
  <dump if="fit-log(fit-serialize(server))" />
  ...
</flow>

Example output of the server Delivery Context properties in the fit_engine.log:

[23-Mar-2017 06:56:33 UTC] WNNxoX8AAAEAAAMKKZQAAACW:myProject <server>
  <fit-version>14.6.3</fit-version>
  <project>myProject</project>
  <role>production</role>
  <site>mySite</site>
  <ucm>3dd4288fa57c4d192785d3dda3b05a73</ucm>
</server>

Using XSLT:

...
  <xsl:variable name="myVar">
    <foo>
      <bar>value</bar>
    </foo>
  </xsl:variable>
...
  <xsl:value-of select="fit-log(fit-serialize($myVar))" />
...

Example output in the fit_engine.log:

[27-Mar-2017 09:06:54 UTC] WNNxoX8AAAEAAAMKKZQAAACW:myProject  <?xml version="1.0"?>
<foo>
  <bar>value</bar>
</foo>

has-class()

boolean has-class(string|node-set class_name [, node-set context])

The function has-class checks whether an element has a class attribute which contains the given CSS class name. The search is case-insensitive. If no context parameter is given, the current context node is used.

Examples

//*[has-class('myClass')] returns all elements which contain the class name myClass in their class attributes.

has-class('myClass', /*) returns true if the document element contains myClass in its class attribute, otherwise false.

Searching for multiple class names simultaneously (e.g. has-class('a b')) is not supported and triggers a warning. Use an and or an or expression instead, e.g. has-class('a') and has-class('b').

Searching an empty string is also not allowed and triggers a warning, too.

json-to-xml()

node-set json-to-xml(string json)

The XPath function json-to-xml translates the given json string into a corresponding XML structure as described in the JSON DOM Structure. If any errors occur, an empty node-set is returned.

lookup()

string lookup(string fidj-file-uri, string key [, string default = ""])

The XPath function lookup returns the value associated with the key in a database file. The database file specified by the fidj-uri can be either in JSON or SHMT format. If the key is not found, the default string will be returned.

  • fidj-file-uri: FIDJ URI pointing to a local database file. The extension of the database file must be either lowercase .json for a JSON file or lowercase .shmt for an SHMT file.
  • key: database key to search for
  • default: optional value to return if the key is not found in the database (default is an empty string "")

Using a JSON file

The JSON DB file has to be implemented as a key-value object (SHMT does this automatically):

{
  "key1": "value1",
  "key2": [1, 2, 3],
  "key3": {"k":"v"}
  ...
}

If a value is either of type object or ordered list of values (array), the value is always converted to a JSON string. By using the json-to-xml() function, the result string can be translated into a corresponding XML structure.

Example:

  <xsl:value-of select="lookup('fit://site/databases/db.json', 'key3')" />

would result in the string "{\"k\":\"v\"}".

Debugging

The lookup XPath function provides many information or error messages in the json debug channel.

Examples

...
  <xsl:value-of select="lookup('fit://project/db/my.json', 'full_name', 'John Doe')" />
...
  <xsl:value-of select="lookup('fit://site/databases/db.shmt', 'key')" />
...

matches()

boolean matches(string input, string pattern [, string modifiers])

The matches function returns true() if input matches the regular expression supplied as pattern as influenced by the value of modifiers, if present; otherwise, it returns false(). Supported modifiers are i (“IGNORECASE”), m (“MULTILINE”), s (“DOTALL”) and x (“EXTENDED”).

Internally, the FIT Server uses PCRE.

Example

matches("FIT", "^f.", "i") evaluates to true()

md5()

string md5(string input)

md5 expects exactly one string parameter and returns a 32 digit hexadecimal representation of its MD5 hash.

replace()

string replace(string input, string pattern, string replacement [, string modifiers])

The function returns a string that is obtained by replacing each non-overlapping substring of the input that matches the given regular expression pattern with an occurrence of the replacement string, respecting the optional modifiers. Supported modifiers are i (“IGNORECASE”), m (“MULTILINE”), s (“DOTALL”) and x (“EXTENDED”).

Internally, the FIT Server uses PCRE.

Examples

  • replace("FIT", "^F", "H") returns HIT.
  • replace("banAna", "na", "l", "i") uses the i modifier for case-insensitive matching and returns ball.

The replacement parameter may use the captured sub-patterns from the pattern parameter with $n or ${n}. Every such $n will be replaced with the text that has been captured by the n’th parenthesized sub-pattern or the empty string if less than n sub-expression were present in the pattern:

  • replace("foo-bar-baz", "b(.)(.)", "b$1$1$1${7}$2$2$2") returns “foo-baaarrr-baaazzz”.

rewrite-url()

string rewrite-url([string URL [, string "ai-mark-or-option-key=value", ...]])

The rewrite-url() XPath function rewrites the given URL according to the options and/or URL Marks. If no URL parameter is given, the value of the current context node is used. You can change the rewriting base URL with the ai-url-base=http... option . By default, the main URL is used.

Each option is passed as a key=value pair without quotes around the value. Options that have no value (e.g. the pass URL Mark) can be passed as key or key=.

Examples

...
  <xsl:value-of select="rewrite-url(., 'ai-mark-pass', 'ai-url-base=http://www.example.com')" />
...
  <xsl:value-of select="rewrite-url('index.html', 'ai-mark-foo=bar', 'ai-url-absolute=true')" />
...

tolower()

string tolower([string|node-set argument])

The tolower XPath function returns the lowercase equivalent of the Unicode representation of the argument. If no argument is given, the value of the current context node is used. As usual, parameters of type node-set are automatically cast to string. Parameters of other types, e.g. number or boolean, are not accepted.

toupper()

string toupper([string|node-set argument])

The toupper XPath function returns the uppercase equivalent of the Unicode representation of the argument. If no argument is given, the value of the current context node is used. As usual, parameters of type node-set are automatically cast to string. Parameters of other types, e.g. number or boolean, are not accepted.

urldecode()

string urlencode(string argument)

urldecode expects exactly one string as a parameter. Returns a string in which the sequences with percent (%) signs followed by two hex digits have been replaced with literal characters.

urlencode()

string urlencode(string argument)

urlencode expects exactly one string as a parameter. Returns a string in which all non-alphanumeric characters except -_.~ have been replaced with a percent (%) sign followed by two hex digits. Cf. RFC 3986

version-compare()

boolean version-compare(string|node-set version1, string|node-set version2, string|node-set operator)

The version-compare XPath function compares two “PHP-standardized” version number strings. It expects exactly three parameters of types string or node-set:

  • version1: The first version
  • version2: The second version
  • operator: The comparison operator

As usual, parameters of type node-set are automatically cast to string. However, an empty node-set is considered an error. Parameters of other types, e.g. number or boolean, are not accepted.

operator may be one of:

  • lt: less than (e.g. 1 < 2)
  • le: less than or equal to (e.g. 1 ≤ 2)
  • gt: greater than (e.g. 2 > 1)
  • ge: greater than or equal to (e.g. 2 ≥ 1)
  • eq: equals (e.g. 1 = 1)
  • ne: not equal to (e.g. 1 ≠ 2)

The delivery context provides various properties containing version information, for example:

Examples

A common use of the version-compare function is in AI filter expressions:

<html>
  …
  <div ai-if="version-compare(client/os/version, '2.3.3', 'ge')">
    OS version 2.3.3 or newer detected.
  </div>
  …
</html>

You may also find version-compare useful in your flow control structures:

<flow>
  <choose>
    <when test="version-compare(server/fit-version, '14', 'ge') and version-compare(server/fit-version, '14.0.3', 'lt')">
      <!-- FIT Server 14.0.0, 14.0.1 or 14.0.2 detected. --></when>
    <otherwise>
      <!-- FIT Server 14.0.3 or newer detected. --></otherwise>
  </choose></flow>

Be careful with comparisons to empty strings as an empty string is considered to be smaller than any nonempty string. Comparing “negative numbers” may also result in unexpected results. Finally, an “integer” is always smaller than the corresponding .0 floating point number. For example, all of the following expressions evaluate to true():


<div ai-if="version-compare('', '0', 'lt')">true()</div>
<div ai-if="version-compare('0.0', '', 'ge)">true()</div>
<div ai-if="version-compare('-1', '-2', 'lt')">true()</div>
<div ai-if="version-compare('4', '4.0', 'lt')">true()</div>

watch()

boolean watch(xpath expression [, string message])

The XPath function watch evaluates a given XPath expression and reports the result to the FIT Engine. This is primarily used for quality assurance. A watch function will not change the result of the expression. It can be used to make problems and unforeseen changes visible or to react to a negative result, for example by displaying an error message.

  • expression: XPath expression to be watched.
  • message: an optional message. Defaults to the given XPath expression.

The result of the XPath expression will be visible in the debug output in the watches channel. If the expression evaluates to false, the message will also be written to the fit_alert.log.

Example fit_alert.log log lines:

2015-12-01 11:12:13+0200 VmaNmn8AAAEAAB3Gy08AAABA myProject (-) mySite XPath watch failed: My info message
2015-12-01 12:13:14+0200 VmaNmn8AAAEAAB3Gy08AAABA myProject (-) mySite XPath watch failed: watch(//foo)

xml-to-json()

string xml-to-json(node-set node)

The XPath function xml-to-json translates the given node into its JSON representation. The structure of the node must take into account the notation of the JSON DOM Structure. The xml-to-json expects exactly one single node as parameter. In cases of errors, an empty string is returned.