Re: [xsl] Recursion

Subject: Re: [xsl] Recursion
From: Vasu Chakkera <vasucv@xxxxxxxxx>
Date: Mon, 28 May 2012 12:26:19 +0100
Thanks Mike.
I will look out for it.
Vasu

On 28 May 2012 12:17, Michael Kay <mike@xxxxxxxxxxxx> wrote:
> You will find some examples of how to look for cycles in a graph in my book
> XSLT 2.0 Programmers Reference, pp251-253 and 353-353 in the 4th edition.
>
> (Don't use the examples in the third edition, where I got them badly wrong!
> - which just goes to show that this problem is quite a tricky one.)
>
> The main differences are (a) I've generalized the solution by detecting
> cycles in ANY graph, using higher-order functions to parameterize the
> solution), and (b) the memory of where you've been in the graph is provided
> as a sequence, not a concatenated string.
>
> For this particular problem you also need to worry about turning the
> schemaLocation values into absolute URIs relative to their containing
> document, and checking for cycles after absolutizing the URI.
>
> Generally, though I would advise against trying to extract schema
> information from raw schema documents - you will get it wrong. It's much
> better to get the information from a schema processor that has already
> pre-digested the schema documents and turned them into a schema component
> model.
>
> Michael Kay
> Saxonica
>
>
> On 28/05/2012 11:58, Vasu Chakkera wrote:
>>
>> Guys,
>>
>> I had this issue, which I solved, but thought someone here could
>> probably recreate with some better ideas?? I did not refractor this..
>> so , I am sure the code can be refractored or rearranged/ beautified
>> .. But I am wanting to see if there is a completely different
>> approach...
>>
>>
>> The problem is as folllows..
>>
>> XSLT is written for an XSD. This XSD may include another XSD and that
>> may include more XSDs and so on and so forth,. This can end up
>> becoming a huge tree.
>> Some where, one of the XSDs can actually refer to another XSD which
>> could have been already in the tree. So a normall thought process is
>> that your XSLT will fail because it will end up into the infinite
>> recursion ( circular reference).. So I wrote this XSLT to process such
>> a tree...  I have simulated this one with XMLS with nodes that are
>> called<includes>  //
>>
>> Main XML :
>> =======
>> <xml1>
>>     <includes>file1.xml</includes>
>>     <includes>file2.xml</includes>
>> </xml1>
>>
>> file1.xml
>> =======
>> <xml1>
>>     <includes>file1.1.xml</includes>
>>     <includes>file1.2.xml</includes>
>> </xml1>
>>
>> file2.xml
>> =======
>> <xml1>
>>     <includes>file2.1.xml</includes>
>>     <includes>file2.2.xml</includes>
>> </xml1>
>> file1.1.xml
>> =======
>> <xml1>
>>     <includes>file1.1.1xml</includes>
>>     <includes>file1.xml
>>  <!-- this one is bad circular reference -->
>> </includes>
>> </xml1>
>>
>>  and so on...
>>
>> The XSLT is
>> ========
>>
>> <?xml version="1.0" encoding="UTF-8"?>
>> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
>> version="2.0">
>>     <xsl:template match="xml1">
>>         <xsl:call-template name="get-include">
>>             <xsl:with-param name="init" select="0"/>
>>         </xsl:call-template>
>>     </xsl:template>
>>     <xsl:template name="get-include">
>>         <xsl:param name="document-name"/>
>>         <xsl:param name="init"/>
>>         <xsl:param name="include-tree"/>
>>         <xsl:choose>
>>             <xsl:when test="$init = 1">
>>                 <xsl:for-each select="document($document-name)//includes">
>>                     <xsl:variable name="doc-name" select="."/>
>>                     <xsl:value-of select="."/>
>>                     <xsl:choose>
>>                         <xsl:when
>> test="contains($include-tree,$doc-name)">
>>                             <xsl:text>: This file is ignored :
>> Circular Reference</xsl:text>
>>                             <xsl:text>&#xa;</xsl:text>
>>                         </xsl:when>
>>                         <xsl:otherwise>
>>                             <xsl:text>,</xsl:text>
>>                             <xsl:call-template name="get-include">
>>                                 <xsl:with-param name="document-name"
>> select="$doc-name"/>
>>                                 <xsl:with-param name="init" select="1"/>
>>                                 <xsl:with-param name="include-tree"
>>
>> select="concat($include-tree,'/',$doc-name,'/')"/>
>>                             </xsl:call-template>
>>                         </xsl:otherwise>
>>                     </xsl:choose>
>>                     <xsl:text>&#xa;</xsl:text>
>>                 </xsl:for-each>
>>             </xsl:when>
>>             <xsl:otherwise>
>>                 <xsl:for-each select="//includes">
>>                     <xsl:text>  &#xa;</xsl:text>
>>                     <xsl:variable name="doc-name" select="."/>
>>                     <xsl:value-of select="."/>
>>                     <xsl:call-template name="get-include">
>>                         <xsl:with-param name="document-name" select="."/>
>>                         <xsl:with-param name="init" select="1"/>
>>                         <xsl:with-param name="include-tree"
>>                             select="concat($include-tree,'/',$doc-name)"/>
>>                     </xsl:call-template>
>>                 </xsl:for-each>
>>             </xsl:otherwise>
>>         </xsl:choose>
>>     </xsl:template>
>>
>> </xsl:stylesheet>
>>
>> Any Ideas??
>>
>> Vasu Chakkera
>



--
Vasu Chakkera
NodeLogic Limited
Oxford
www.node-logic.com
==============

Current Thread