xsl-list
[Top] [All Lists]

Re: [xsl] XPath 2.0 expression that detects a cycle of references?

2016-03-30 23:41:30
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-functions-in-xpath-3-0-2/

Wow, 2012! And mentioning Roger Costello…


There are two other places where this technique was presented:

[1] Balisage 2013, "Programming in XPath 3.1"

[2] The Evolution of XPath: What’s New in XPath 3.0 -- a video
training course at Pluralsight, 2013


Programming in pure XPath is a powerful way of producing valuable
modules that are completely portable and independent of any
vendor-specific XSLT or XQuery processors -- thus achieving maximum
spread and (re)usability regardless of platform or programming
language. This could be one reason why XSLT/XQuery vendors -- even
those who are aware of this --  rarely, if at all, mention XPath
programming... :)



Roger certainly knows about this technique, because he was de facto a
co-author of [1]. This is why he specifically asks about an XPath 2.0
solution.


The technique described in [1] and [2] was used (in a comprehensive
example) for implementing, instantiating and using a new,
custom-defined data-type in XPath 3.0 -- the Binary Search Tree
datatype.

While the Balisage paper was limited in time, the Pluralsight course
dedicates a single, 40-minutes module on XPath 3.0 programming,
preceded by another 17 minutes+  single clip on implementing recursion
using anonymous functions in XPath 3.0.


Links:

[1] Paper: 
http://www.balisage.net/Proceedings/vol10/html/Novatchev01/BalisageVol10-Novatchev01.html
,
     Slides: 
http://www.balisage.net/Proceedings/vol10/author-pkg/Novatchev01/BalisageVol10-Novatchev01.html

[2] Course: https://www.pluralsight.com/courses/xpath-3-0-whats-new



Cheers,
Dimitre

On Tue, Mar 29, 2016 at 4:19 AM, Michael Müller-Hillebrand
mmh(_at_)docufy(_dot_)de 
<xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com> wrote:

Martin Honnen wrote:

I have no idea how one would have to handle this using XPath 3… 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-functions-in-xpath-3-0-2/

Wow, 2012! And mentioning Roger Costello…

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>





-- 
Cheers,
Dimitre Novatchev
---------------------------------------
Truly great madness cannot be achieved without significant intelligence.
---------------------------------------
To invent, you need a good imagination and a pile of junk
-------------------------------------
Never fight an inanimate object
-------------------------------------
To avoid situations in which you might make mistakes may be the
biggest mistake of all
------------------------------------
Quality means doing it right when no one is looking.
-------------------------------------
You've achieved success in your field when you don't know whether what
you're doing is work or play
-------------------------------------
To achieve the impossible dream, try going to sleep.
-------------------------------------
Facts do not cease to exist because they are ignored.
-------------------------------------
Typing monkeys will write all Shakespeare's works in 200yrs.Will they
write all patents, too? :)
-------------------------------------
Sanity is madness put to good use.
-------------------------------------
I finally figured out the only reason to be alive is to enjoy it.
--~----------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
EasyUnsubscribe: http://lists.mulberrytech.com/unsub/xsl-list/1167547
or by email: xsl-list-unsub(_at_)lists(_dot_)mulberrytech(_dot_)com
--~--

<Prev in Thread] Current Thread [Next in Thread>