I am failing with a seemingly simple task.
I have a configuration file which defines different scenarios. Each scenario has a test expression. The idea is, that instructions within the scenario shall be applied to input documents which match the test expression. For example:
<config>
<scenario test="/input/@id eq 'X'">
...
</scenario>
<scenario test="/input/@id eq 'Y'">
...
</scenario>
</config>
My Problem / Question is: With a given input File, how to identify the matching scenario?
Let $d be a variable with some document node. I can check if it matches the pattern P by writing $d[P]. So i tried with something like
let $p:=doc("config.xml")/config/scenario/@test,
$d:=doc("input.xml")
return $d[$p]
I expected an non-empty sequence if and only if the input Document $i matches the test Pattern $p. But the result of the expression is never empty, no matter what the @test Attribute is. Even if there is just one scenario with a test expression that definitive does not match.
Thanks in advance, Frank
CodePudding user response:
In your example the variable $p
is a sequence of attributes, and when you use that $p
in your predicate, it's converted to a boolean value, as if by the boolean()
function. The XPath spec says:
If its operand is a sequence whose first item is a node, fn:boolean returns true.
So if your config file has any test scenarios, then the predicate will return true.
What you need to do is evaluate that expression.
CodePudding user response:
XPath evaluation can be done in XSLT 3.0 using xsl:evaluate
:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:mf="http://example.com/mf"
exclude-result-prefixes="#all"
version="3.0">
<xsl:function name="mf:evaluate-predicate" as="item()*">
<xsl:param name="context-item" as="item()"/>
<xsl:param name="predicate" as="xs:string"/>
<xsl:evaluate context-item="$context-item" xpath="'.[' || $predicate || ']'"/>
</xsl:function>
<xsl:template match="/input[some $pred in $config/config/scenario/@test satisfies mf:evaluate-predicate(., $pred)]">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:param name="config" select="doc('config.xml')"/>
</xsl:stylesheet>
xsl:evaluate
is an optional feature, it was not supported in early XSLT 3 Saxon HE version (i.e. 9.8 and 9.9) but is supported in Saxon HE 10 and 11 (and of course in PE/EE since 9.8). It is also supported in SaxonJS 2.