FIT provides a number of XPath functions that are not part of XPath 1.0, but should prove useful when working with FIT.
content()
ends-with()
fit-document()
fit-log()
fit-serialize()
has-class()
json-to-xml()
lookup()
matches()
md5()
replace()
rewrite-url()
tolower()
toupper()
urldecode()
urlencode()
version-compare()
watch()
xml-to-json()
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
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
.
ends-with("foo", "oo")
returns true
ends-with(request/url, ".json")
could be used to identify JSON resourcesfit-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.
<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.
message
: a message to be written into the fit_engine.log
<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
.
<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.
//*[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 fordefault
: optional value to return if the key
is not found in the database (default is an empty string ""
)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\"}"
.
The lookup
XPath function provides many information or error messages in the json
debug channel.
...
<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
.
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
.
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=
.
...
<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 versionversion2
: The second versionoperator
: The comparison operatorAs 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:
client/version
client/render-engine/version
client/os/version
server/fit-version
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.