<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE stylesheet [
  <!ENTITY rdfnsuri "http://www.w3.org/1999/02/22-rdf-syntax-ns#">
]>

  
<!-- 
Parser_#5c, a Canonicalised-RDF to N-triples XSLT transform

Copyright © 2002 Max Froumentin

Use and distribution of this code are permitted under the terms of the <a
href="http://www.w3.org/Consortium/Legal/copyright-software-19980720"
>W3C Software Notice and License</a>.
-->


<stylesheet xmlns="http://www.w3.org/1999/XSL/Transform"
            xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
            version="1.0">


  <output method="xml" omit-xml-declaration="yes"  encoding="US-ASCII" />
  <strip-space elements="*"/>


  <param name="base" select="''"/>


  <param name="debug" select="0"/>

  <!-- if there's an xml:base attribute use it as the base URI, otherwise -->
  <!-- use the one passed as parameter $base -->
       
  <variable name="baseURI">
    <choose>
      <when test="rdf:RDF/@xml:base">
        <choose>
          <!-- if the baseURI has a fragment identifier, remove it -->
          <when test="contains(rdf:RDF/@xml:base,'#')">
            <value-of select="substring-before(rdf:RDF/@xml:base,'#')"/>
          </when>
          <otherwise>
            <value-of select="rdf:RDF/@xml:base"/>
          </otherwise>
        </choose>
      </when>
      <otherwise>
        <value-of select="$base"/>
      </otherwise>
    </choose>
  </variable>

  
  <!-- ================================================================= -->

  <template match="/"><apply-templates/></template>
  <template match="rdf:RDF"><apply-templates/></template>

  <!-- ================================================================= -->

  <template match="rdf:Description">
    <if test="$debug > 0">
      <text># N-triples for node: </text>
      <value-of select="concat(local-name(),'&#xa;')"/>
    </if>

    <!-- process the arcs -->
    <apply-templates/>
  </template>
    
  <!-- ==================================================================== -->

  <template match="*">
    <if test="$debug > 0">
      <text># N-triples for arc: </text>
      <value-of select="concat(local-name(),'&#xa;')"/>
    </if>


    <!-- 1st element of triple: subject (id of parent) -->


    <variable name="subject">
      <!-- we put the subject in a variable as it could be used later -->
      <!-- if we reify the statement -->
      <choose>
        <when test="../@rdf:about">
          <text>&lt;</text>
          <variable name="resolvedURI">
            <call-template name="expand">
              <with-param name="base" select="$baseURI"/>
              <with-param name="there" select="../@rdf:about"/>
            </call-template>
          </variable>
          <!--
          <value-of select="$baseURI"/>
          <if test="$baseURI!='' and ../@rdf:about!=''">#</if>
          <value-of select="concat(../@rdf:about,'&gt;')"/>
          -->
          <value-of select="concat($resolvedURI,'&gt;')"/>
        </when>

        <when test="../@rdf:ID">
          <value-of select="concat('&lt;',$baseURI,'#',../@rdf:ID,'&gt;')"/>
        </when>

        <when test="../@rdf:nodeID">
          <value-of select="concat('_:',../@rdf:nodeID)"/>
        </when>

        <otherwise>
          <!-- no ID or parent about: this is probably a bNode -->
          <value-of select="concat('_:',generate-id(..))"/>
        </otherwise>
      </choose>
    </variable>


    <!-- 2nd element: predicate (URI of node) -->


    <variable name="predicate">
      <choose>
        <when test="self::rdf:li">
          <value-of select="concat('&lt;',namespace-uri(),'_',count(preceding-sibling::rdf:li|.),'&gt;')"/>
        </when>
        <otherwise>
          <value-of select="concat('&lt;',namespace-uri(),local-name(),'&gt;')"/>
        </otherwise>
      </choose>
    </variable>    

    <!-- 3rd element: object (URI or literal) -->
    <variable name="object">
      <choose>
        <when test="@rdf:parseType='Literal'">
          <!-- target is a "forced" literal -->

          <!-- dump contents. Any " must be escaped to \" -->
          <value-of select="concat('xml&quot;',translate(.,'&quot;','\&quot;'),'&quot;')"/>
          <if test="@rdf:datatype">
            <value-of select="concat('^^&lt;',@rdf:datatype,'&gt;')"/>
          </if>
        </when>

        <when test="@rdf:resource">
          <!-- target is a resource -->
          <variable name="r">
            <call-template name="expand">
              <with-param name="base" select="$baseURI"/>
              <with-param name="there" select="@rdf:resource"/>
            </call-template>
          </variable>

          <value-of select="concat('&lt;',$r,'&gt;')"/>

          <!--
          <value-of select="concat('&lt;',$baseURI,@rdf:resource,'&gt;')"/>
          -->
        </when>

        <when test="child::text()">
          <!-- target is a literal -->
          <value-of select="concat('&quot;',.,'&quot;')"/>
          <if test="@rdf:datatype">
            <value-of select="concat('^^&lt;',@rdf:datatype,'&gt;')"/>
          </if>
        </when>
        


        <!-- target is an RDF container rdf:Resource, rdf:Bag, -->
        <!-- rdf:Seq, rdf:Alt -->
        <!-- I assume those never have rdf:about -->
        <!--        <when test="namespace-uri(child::*)=&rdfnsuri;">-->

        <when test="child::*">
          <value-of select="concat('_:',generate-id(child::*))"/>
        </when>

        <!-- arc has a child: it is the object, a bNode -->
        <!--
        <when test="*">
          <value-of select="concatgenerate-id(*[1])"/>
        </when>
-->
        <!-- arc has no target attributes or children -->
        <!-- object is then empty string -->
        <when test="not(@*[not(namespace-uri()='&rdfnsuri;')])">
          <text>""</text>
        </when>
      </choose>
    </variable>

    <!-- if there's a reason to print this, do it -->
    <!-- how helpful the above line is ;-) -->
    <!-- basically, this test means: it the value of $object has been -->
    <!-- computed above, output the triple -->
    <!-- (there must be a more elegant way to do this) -->
         
    <if test="* or text() or @rdf:resource or not(@*[not(namespace-uri()='&rdfnsuri;')])">
      <value-of select="concat($subject,' ')" disable-output-escaping="yes"/>
      <value-of select="concat($predicate,' ')" disable-output-escaping="yes"/>
      <value-of select="concat($object,' .&#xa;')" disable-output-escaping="yes"/>
    </if>
    
    <!-- if target has an rdf:ID, the statement should be -->
    <!-- reified it seems. Not sure why (from example test0005.rdf) -->
    
    <if test="@rdf:ID">
      <!-- First n-triple: type -->
      
      <!-- subject -->
      <value-of select="concat('&lt;',$baseURI,'#',@rdf:ID,'&gt; ')"   disable-output-escaping="yes"/>
      <!-- predicate -->
      <text disable-output-escaping="yes">&lt;&rdfnsuri;type&gt; </text>
      <!-- object -->
      <text disable-output-escaping="yes">&lt;&rdfnsuri;Statement&gt; .&#xa;</text>
      <!-- Second n-triple: subject -->

      <!-- subject -->
      <value-of select="concat('&lt;',$baseURI,'#',@rdf:ID,'&gt; ')"   disable-output-escaping="yes"/>
      <!-- predicate -->
      <text disable-output-escaping="yes">&lt;&rdfnsuri;subject&gt; </text>
      <!-- object -->
      <value-of select="concat($subject,' .&#xa;')" disable-output-escaping="yes"/>

      <!-- Second n-triple: predicate -->

      <!-- subject -->
      <value-of select="concat('&lt;',$baseURI,'#',@rdf:ID,'&gt; ')" disable-output-escaping="yes"/>
      <!-- predicate -->
      <text disable-output-escaping="yes">&lt;&rdfnsuri;predicate&gt; </text>
      <!-- object -->
      <value-of select="concat($predicate,' . &#xa;')"  disable-output-escaping="yes"/>

      <!-- Third n-triple: object -->
      <!-- subject -->
      <value-of select="concat('&lt;',$baseURI,'#',@rdf:ID,'&gt; ')"  disable-output-escaping="yes"/>
      <!-- predicate -->
      <text disable-output-escaping="yes">&lt;&rdfnsuri;object&gt; </text>
      <!-- object -->
      <value-of select="concat($object,' . &#xa;')" disable-output-escaping="yes"/>

    </if>

    <!-- process children Resource -->
    <apply-templates select="rdf:Description"/>
  </template>        

<!--########################################################################-->
<!--########################################################################-->
<!--########################################################################-->
<!--########################################################################-->

  <!-- From here on, the templates are from Dan Connoly's URI
       absolutizer. They used to be <include>d but have been included
       to make users lifes simpler (few bugs fixed too)
   -->
  
<!--
<div xmlns="http://www.w3.org/1999/xhtml">

<h2>Share and Enjoy</h2>

<p>$ uri.xsl,v 1.6 2000/09/08 08:06:31 connolly Exp $</p>

<p>Copyright (c) 2000 W3C (MIT, INRIA, Keio), released under the <a
href="http://www.w3.org/Consortium/Legal/copyright-software-19980720">
W3C Open Source License</a> of August 14 1998.  </p>

<h2>Reference</h2>

<p><cite><a href="http://www.ietf.org/rfc/rfc2396.txt">Uniform
    Resource Identifiers (URI): Generic Syntax</a></cite> (RFC 2396)
    T. Berners-Lee, R. Fielding, L. Masinter August 1998 </p>

</div>
-->

<variable name="lowalpha"
	      select='"abcdefghijklmnopqrstuvwxyz"'/>
<variable name="upalpha"
	      select='"ABCDEFGHIJKLMNOPQRSTUVWXYZ"'/>
<variable name="digit"
	      select='"01234567890"'/>
<variable name="alpha"
	      select='concat($lowalpha, $upalpha)'/>

<param name="Debug" select="0"/>

<template name="expand">
  <!-- 5.2. Resolving Relative References to Absolute Form -->
  <param name="base"/> <!-- an absolute URI -->
  <param name="there"/> <!-- a URI reference -->

  <!-- @@assert that $there contains only URI characters -->
  <!-- @@implement the unicode->ascii thingy from HTML 4.0 -->

  <variable name="fragment" select='substring-after($there, "#")'/>
		<!-- hmm... I'd like to split after the *last* #,
		     but substring-after splits after the first occurence.
		     Anyway... more than one # is illegal -->

  <variable name="hashFragment">
    <choose>
      <when test="string-length($fragment) > 0">
        <value-of select='concat("#", $fragment)'/>
      </when>
      <otherwise>
        <value-of select='""'/>
      </otherwise>
    </choose>
  </variable>
  <variable name="rest"
		select='substring($there, 1,
			          string-length($there)
				  - string-length($hashFragment))'/>

  <if test="$Debug"><message>
     [<value-of select="$there"/>]
     [<value-of select="$fragment"/>]
     [<value-of select="$hashFragment"/>]
     [<value-of select="$rest"/>]
  </message></if>

  <choose>
    <!-- step 2) -->
    <when test="string-length($rest) = 0">
      <if test="0">
      <message>expand called with reference to self-same document.
			     should this be prohibited? i.e.
			     should the caller handle references
			     to the self-same document?</message>
      </if>
      <value-of select="concat($base, $hashFragment)"/>
    </when>

    <otherwise>
      <variable name="scheme">
        <call-template name="split-scheme">
	  <with-param name="ref" select="$rest"/>
	</call-template>
      </variable>

      <choose>
        <when test='string-length($scheme) > 0'>
	  <!-- step 3) ref is absolute. we're done -->
	  <value-of select="$there"/>
	</when>

        <otherwise>
	  <variable name="rest2"
			select='substring($rest, string-length($scheme) + 1)'/>

	  <variable name="baseScheme">
	    <call-template name="split-scheme">
	    <with-param name="ref" select="$base"/>
	    </call-template>
	  </variable>

	  <choose>
	    <when test='starts-with($rest2, "//")'>
	      <!-- step 4) network-path; we're done -->

	      <value-of select='concat($baseScheme, ":",
					   $rest2, $hashFragment)'/>
            </when>

	    <otherwise>

	      <variable name="baseRest"
			    select='substring($base,
				 string-length($baseScheme) + 2)'/>

	      <variable name="baseAuthority">
		<call-template name="split-authority">
		  <with-param name="ref" select="$baseRest"/>
		</call-template>
	      </variable>

	      <choose>
	        <when test='starts-with($rest2, "/")'>
		  <!-- step 5) absolute-path; we're done -->

		  <value-of select='concat($baseScheme, ":",
					       $baseAuthority,
					       $rest2, $hashFragment)'/>
		</when>

		<otherwise>
		  <!-- step 6) relative-path -->
		  <!-- @@ this part of the implementation is *NOT*
		       per the spec, because I want combine(wrt(x,y))=y
		       even in the case of y = foo/../bar
		       -->

		  <variable name="baseRest2"
			    select='substring($baseRest,
				 string-length($baseAuthority) + 1)'/>

		  <variable name="baseParent">
		    <call-template name="path-parent">
		      <with-param name="path" select="$baseRest2"/>
		    </call-template>
		  </variable>

		  <variable name="path">
		    <call-template name="follow-path">
		      <with-param name="start" select="$baseParent"/>
		      <with-param name="path" select="$rest"/>
		    </call-template>
		  </variable>

		  <if test="$Debug"><message>
		    step 6 rel
		     [<value-of select="$rest2"/>]
		     [<value-of select="$baseRest2"/>]
		     [<value-of select="$baseParent"/>]
		     [<value-of select="$path"/>]
		  </message></if>

		  <value-of select='concat($baseScheme, ":",
					       $baseAuthority,
					       $path,
					       $hashFragment)'/>
		</otherwise>
	      </choose>
	    </otherwise>
	  </choose>

        </otherwise>
      </choose>
    </otherwise>
  </choose>
</template>


<template name="split-scheme">
  <!-- from a URI reference -->
  <param name="ref"/>

  <variable name="scheme_"
		    select='substring-before($ref, ":")'/>
  <choose>
    <!-- test whether $scheme_ is a legal scheme name,
	 i.e. whether it starts with an alpha
	 and contains only alpha, digit, +, -, .
	 -->
    <when
      test='string-length($scheme_) > 0
            and contains($alpha, substring($scheme_, 1, 1))
	    and string-length(translate(substring($scheme_, 2),
			                concat($alpha, $digit,
					       "+-."),
				        "")) = 0'>
	  <value-of select="$scheme_"/>
    </when>

    <otherwise>
      <value-of select='""'/>
    </otherwise>
  </choose>
</template>


<template name="split-authority">
  <!-- from a URI reference that has had the fragment identifier
       and scheme removed -->
       <!-- cf 3.2. Authority Component -->

  <param name="ref"/>

  <choose>
    <when test='starts-with($ref, "//")'>
      <variable name="auth1" select='substring($ref, 3)'/>
      <variable name="auth2">
        <choose>
          <when test='contains($auth1, "?")'>
	    <value-of select='substring-before($auth1, "?")'/>
	  </when>
	  <otherwise><value-of select="$auth1"/>
	  </otherwise>
	</choose>
      </variable>

      <variable name="auth3">
        <choose>
          <when test='contains($auth2, "/")'>
	    <value-of select='substring-before($auth1, "/")'/>
	  </when>
	  <otherwise><value-of select="$auth2"/>
	  </otherwise>
	</choose>
      </variable>

      <value-of select='concat("//", $auth3)'/>
    </when>

    <otherwise>
      <value-of select='""'/>
    </otherwise>
  </choose>
</template>

<template name="follow-path">
  <param name="start"/> <!-- doesn't end with / ; may be empty -->
  <param name="path"/> <!-- doesn't start with / -->

  <if test="$Debug"><message>
    follow-path
     [<value-of select="$start"/>]
     [<value-of select="$path"/>]
  </message></if>

  <choose>
    <when test='starts-with($path, "./")'>
      <call-template name="follow-path">
        <with-param name="start" select="$start"/>
	<with-param name="path" select='substring($path, 3)'/>
      </call-template>
    </when>

    <when test='starts-with($path, "../")'>
      <call-template name="follow-path">
        <with-param name="start">
	  <call-template name="path-parent">
	    <with-param name="path" select="$start"/>
	  </call-template>
	</with-param>
	<with-param name="path" select='substring($path, 4)'/>
      </call-template>
    </when>

    <otherwise>
      <value-of select='concat($start, "/", $path)'/>
    </otherwise>
  </choose>
</template>


<template name="path-parent">
  <param name="path"/>

  <if test="$Debug"><message>
    path parent
     [<value-of select="$path"/>]
  </message></if>

  <choose>
	      <!-- foo/bar/    => foo/bar    , return -->
    <when test='substring($path, string-length($path)) = "/"'>
      <value-of select='substring($path, 1, string-length($path)-1)'/>
    </when>

	      <!-- foo/bar/baz => foo/bar/ba , recur -->
	      <!-- foo/bar/ba  => foo/bar/b  , recur -->
	      <!-- foo/bar/b   => foo/bar/   , recur -->
    <when test='contains($path, "/")'>
      <call-template name="path-parent">
        <with-param name="path"
		   select='substring($path, 1, string-length($path)-1)'/>
      </call-template>
    </when>

	      <!-- '' => '' -->
	      <!-- foo => '' -->
    <otherwise>
      <value-of select='""'/>
    </otherwise>

  </choose>

</template>

</stylesheet>
