Subject: Re: [xsl] Compare logical expressions with XPath/XSLT From: "Michael Kay mike@xxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> Date: Thu, 7 Mar 2019 21:10:53 -0000 |
Here's a refinement of this approach (a) translate the expressions into XPath syntax ("A AND !B" ==> "$a and not($b)") (b) evaluate something like if (some $a in (true(), false()), $b in (true(), false()), $c in (true(), false()) satisfies eval(X, $a, $b, $c) and not eval(Y, $a, $b, $c)) then .... where eval() invokes xsl:evaluate with appropriate parameters. This basically differs from David Carlisle's approach in two ways: (i) enumerating the truth tables is done incrementally without actually storing the result in a variable (ii) the boolean expression is compiled into XPath rather than being interpreted. Michael Kay Saxonica > On 7 Mar 2019, at 20:52, David Carlisle d.p.carlisle@xxxxxxxxx <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote: > > if I understood you correctly you have a fixed number of boolean > variables (3 here) so you can enumerate the truth table of each > project and want to know that the expression for the sub project is > never true if the expression for the main project is false. > > this is not, to put it mildly, well tested but I get > > $ saxon9 -it:main prg.xsl > project 1 and 2 > false > project 1 and 3 > true > > > from the following which assumes AND and OR always have exactly two > children and that my typing is accurate, neither of which assumption > may be true... > > <xsl:stylesheet version="2.0" > xmlns:xsl="http://www.w3.org/1999/XSL/Transform" > xmlns:xs="http://www.w3.org/2001/XMLSchema" > xmlns:f="data:,f"> > > <xsl:variable name="defs" as="element()"> > <defs> > <def name="project-1"> > <set> > <AND> > <OR> > <item required="false">A</item> > <item required="false">B</item> > </OR> > <item required="false">C</item> > </AND> > </set> > </def> > <def name="project-2"> > <set> > <OR> > <item required="true">A</item> > <item required="true">C</item> > </OR> > </set> > </def> > <def name="project-3"> > <set> > <item required="false">C</item> > </set> > </def> > </defs> > </xsl:variable> > > <xsl:template name="main"> > <xsl:message select="'project 1 and 2'"/> > <xsl:message select="f:check($defs/def[@name='project-1']/set/*,$defs/def[@name='project-2 ']/set/*)"/> > <xsl:message select="'project 1 and 3'"/> > <xsl:message select="f:check($defs/def[@name='project-1']/set/*,$defs/def[@name='project-3 ']/set/*)"/> > </xsl:template> > > <xsl:function name="f:check" as="xs:boolean"> > <xsl:param name="p1" as="element()"/> > <xsl:param name="p2" as="element()"/> > <xsl:variable name="tt1" as="xs:boolean*"> > <xsl:sequence select=" > for $a in (true(),false()),$b in (true(),false()),$c in (true(),false()) > return > f:eval($p1,$a,$b,$c) > "/> > </xsl:variable> > <xsl:variable name="tt2" as="xs:boolean*"> > <xsl:sequence select=" > for $a in (true(),false()),$b in (true(),false()),$c in (true(),false()) > return > f:eval($p2,$a,$b,$c) > "/> > </xsl:variable> > <xsl:variable name="x" as="xs:boolean*"> > <xsl:for-each select="$tt1"> > <xsl:variable name="pn" select="position()"/> > <xsl:sequence select="not(.) or $tt2[$pn]"/> > </xsl:for-each> > </xsl:variable> > <xsl:sequence select="every $i in $x satisfies $i"/> > </xsl:function> > > <xsl:function name="f:eval" as="xs:boolean"> > <xsl:param name="p" as="element()"/> > <xsl:param name="a" as="xs:boolean"/> > <xsl:param name="b" as="xs:boolean"/> > <xsl:param name="c" as="xs:boolean"/> > <xsl:choose> > <xsl:when test="$p/self::item[.='A']"> > <xsl:sequence select="if($p/@required='true') then $a else not($a)"/> > </xsl:when> > <xsl:when test="$p/self::item[.='B']"> > <xsl:sequence select="if($p/@required='true') then $b else not($b)"/> > </xsl:when> > <xsl:when test="$p/self::item[.='C']"> > <xsl:sequence select="if($p/@required='true') then $c else not($c)"/> > </xsl:when> > <xsl:when test="$p/self::AND"> > <xsl:sequence select="f:eval($p/*[1],$a,$b,$c) and > f:eval($p/*[2],$a,$b,$c)"/> > </xsl:when> > <xsl:when test="$p/self::OR"> > <xsl:sequence select="f:eval($p/*[1],$a,$b,$c) or f:eval($p/*[2],$a,$b,$c)"/> > </xsl:when> > <xsl:otherwise> > <xsl:sequence select="false()(:shouldn't happen:)"/> > </xsl:otherwise> > </xsl:choose> > </xsl:function> > > </xsl:stylesheet>
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] Compare logical expressio, David Carlisle d.p.c | Thread | [xsl] Xsl stylesheet version =1 wit, Vasu Chakkera vasucv |
Re: [xsl] Compare logical expressio, David Carlisle d.p.c | Date | Re: [xsl] XSLT repetition construct, Mukul Gandhi gandhi. |
Month |