[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message] Re: XPath 2.0 expression that detects a cycle of refe
> Martin Honnen wrote: > >> I have no idea how one would have to handle this using XPath 3b& any suggestions? > > Dimitre has an article on using two anonymous function together with "let", to implement the recursion: > > https://dnovatchev.wordpress.com/2012/10/15/recursion-with-anonymous-inline-f unctions-in-xpath-3-0-2/ Wow, 2012! And mentioning Roger Costellob& Assuming my original function worked correctly, this would be the XPath 3.0 version of it: let $f := function( $this as element()+, $visited as xs:string*, $f1 as function(element(), xs:string*, function(*)) as xs:boolean ) as xs:boolean { let $refId := $this/for-more-info/@idref, $refTgt := $this/../item[@id = $refId] return if (not(exists($refTgt))) then false() else if ($refId = $visited) then true() else some $e in $refTgt satisfies $f1($e, ($visited, $refId), $f1) } return $f(., (), $f) At least with Saxon 9.6.0.7 (in Oxygen) in gives the same results. Thanks a lot for hints, I learned quite a bit! - Michael Complete example: Input: <?xml version="1.0" encoding="UTF-8"?> <document> <item id="HF"> <title>Huckleberry Finn</title> <for-more-info idref="MT"/> </item> <item id="MT"> <name>Mark Twain</name> <for-more-info idref="SP"/> <for-more-info idref="ZP"/> </item> <item id="SP"> <publisher>Springer</publisher> <for-more-info idref="HF"/> </item> <item id="XP"> <publisher>XPress</publisher> <for-more-info idref="HF"/> </item> <item id="YP"> <publisher>YPress</publisher> <for-more-info idref="ZP"/> </item> <item id="ZP"> <publisher>ZPress</publisher> </item> </document> Stylesheet including both options as attributes cycle2 (XSLT function) and cycle3 (Xpath 3.0): <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:my="my" exclude-result-prefixes="#all" version="3.0"> <xsl:output indent="yes"/> <xsl:template match="document"> <report> <xsl:for-each select="item"> <xsl:copy> <xsl:copy-of select="@id"/> <xsl:attribute name="cycle2" select="my:CycleFound(., ())"/> <xsl:attribute name="cycle3" select=" let $f := function( $this as element()+, $visited as xs:string*, $f1 as function(element(), xs:string*, function(*)) as xs:boolean ) as xs:boolean { let $refId := $this/for-more-info/@idref, $refTgt := $this/../item[@id = $refId] return if (not(exists($refTgt))) then false() else if ($refId = $visited) then true() else some $e in $refTgt satisfies $f1($e, ($visited, $refId), $f1) } return $f(., (), $f) " /> </xsl:copy> </xsl:for-each> </report> </xsl:template> <xsl:function name="my:CycleFound" as="xs:boolean"> <xsl:param name="this" as="element()?"/> <xsl:param name="visited" as="xs:string*"/> <xsl:variable name="refId" select="$this/for-more-info/@idref" as="xs:string*"/> <xsl:variable name="refTgt" select="$this/../item[@id = $refId]" as="element()*"/> <xsl:sequence select=" if (not(exists($refTgt))) then false() else if ($refId = $visited) then true() else some $e in $refTgt satisfies my:CycleFound($e, ($visited, $e/@id)) "/> </xsl:function> </xsl:stylesheet> [demime 1.01d removed an attachment of type application/pgp-signature which had a name of signature.asc]
|
PURCHASE STYLUS STUDIO ONLINE TODAY!Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced! Download The World's Best XML IDE!Accelerate XML development with our award-winning XML IDE - Download a free trial today! Subscribe in XML format
|