|
[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
|

Cart








