<!-- 
RDFXMLtoRdfXS.xsl - XSLT to transform RDF to database API calls.
- based on http://www.w3.org/2002/03/11-RDF-XSL/rdfToDB.xsl
description and revision history at http://www.w3.org/2002/03/11-RDF-XSL/
$Id: RDFXMLtoRdfXS.xsl,v 1.3 2004/02/10 00:13:34 eric Exp $
-->
<xsl:transform version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:r="http://www.w3.org/1999/02/22-rdf-syntax-ns#">

  <!-- You must manually set your output library here 'cause
       XSLT won't allow parameter definition before an import.
       I would prefer
xsltproc - -stringparam output RdfXStoNTriple.xsl RDFXMLtoRdfXS.xsl test.rdf
  -->
  <xsl:import href="RdfXStoNTriple.xsl"/>
  <xsl:output method="text"/>

  <xsl:param name="baseURI"/>

<!-- xsl:value-of select="concat('/ at:', local-name(.), '&#xA;')"/ -->

  <xsl:template match="/">
    <xsl:call-template name="startDocument"/>
    <xsl:call-template name="root"/>
    <xsl:call-template name="endDocument"/>
  </xsl:template>

  <xsl:template name="root">
    <xsl:choose>

      <xsl:when test=".=/">

        <xsl:for-each select="*">
          <xsl:call-template name="RDF_0"/>
        </xsl:for-each>

      </xsl:when>

      <!-- didn't match any productions -->
      <xsl:otherwise>
        <xsl:call-template name="error">
          <xsl:with-param name="hint" select="'unexpected element'"/>
          <xsl:with-param name="expected" select="'/'"/>
        </xsl:call-template>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template name="RDF_0">
    <xsl:choose>

      <!-- doc RDF -->
      <xsl:when test="self::r:RDF">

        <!-- expect only attributes: xml:lang, xml:base -->
        <xsl:for-each select="./@*">
          <xsl:choose>
            <xsl:when test="self::xml:lang"/>
            <xsl:when test="self::xml:base"/>
            <xsl:otherwise>
              <xsl:call-template name="error">
                <xsl:with-param name="hint" select="'unexpected attribute'"/>
                <xsl:with-param name="expected" select="'&lt;rdf:RDF&gt; @xml:lang?, @xml:base?'"/>
              </xsl:call-template>
            </xsl:otherwise>
          </xsl:choose>
        </xsl:for-each>

        <xsl:for-each select="*">
          <xsl:call-template name="nodeElement_0"/>
        </xsl:for-each>

      </xsl:when>

      <!-- didn't match any productions -->
      <xsl:otherwise>
        <xsl:call-template name="error">
          <xsl:with-param name="hint" select="'unexpected element'"/>
          <xsl:with-param name="expected" select="'<rdf:RDF> @xml:lang?, @xml:base?'"/>
        </xsl:call-template>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>


  <!-- nodeElement - a typed node that is the implied object of arcs  -->
  <xsl:template name="nodeElement_0">
    <xsl:param name="predicate" select="'NULL'"/>
    <xsl:param name="subject" select="'NULL'"/>

        <!-- expect only attributes: @r:ID=xsd:NMTOKEN, @r:nodeID=xsd:NMTOKEN, @r:about, @xml:lang, @xml:base, @&lt;*&gt; -->
        <xsl:for-each select="./@*">
          <xsl:choose>
            <xsl:when test="self::r:ID"/>
            <xsl:when test="self::r:nodeID"/>
            <xsl:when test="self::r:about"/>
            <xsl:when test="self::xml:lang"/>
            <xsl:when test="self::xml:base"/>
            <xsl:otherwise>
              <xsl:call-template name="error">
                <xsl:with-param name="hint" select="'unexpected attribute'"/>
                <xsl:with-param name="expected" select="' @r:ID=xsd:NMTOKEN, @r:nodeID=xsd:NMTOKEN, @r:about, @xml:lang, @xml:base, @&lt;*&gt;'"/>
              </xsl:call-template>
            </xsl:otherwise>
          </xsl:choose>
        </xsl:for-each>

    <!-- look for the name of the nodeElement -->
    <xsl:choose>
      <!-- r:about -->
      <xsl:when test="@r:about">
	<xsl:call-template name="nodeElement_1">
	  <xsl:with-param name="predicate" select="$predicate"/>
	  <xsl:with-param name="subject" select="$subject"/>
	  <xsl:with-param name="object" select="concat('&lt;', @r:about, '&gt;')"/>
	</xsl:call-template>
      </xsl:when>

      <!-- r:ID -->
      <xsl:when test="@r:ID">
	<xsl:call-template name="nodeElement_1">
	  <xsl:with-param name="predicate" select="$predicate"/>
	  <xsl:with-param name="subject" select="$subject"/>
	  <xsl:with-param name="object" select="concat('&lt;', $baseURI, '#', @r:ID, '&gt;')"/>
	</xsl:call-template>
      </xsl:when>

      <!-- r:nodeId -->
      <xsl:when test="@r:nodeId">
	<xsl:call-template name="nodeElement_1">
	  <xsl:with-param name="predicate" select="$predicate"/>
	  <xsl:with-param name="subject" select="$subject"/>
	  <xsl:with-param name="object" select="concat('_:n', @r:nodeId)"/>
	</xsl:call-template>
      </xsl:when>

      <!-- bnode -->
      <xsl:otherwise>
	<xsl:call-template name="nodeElement_1">
	  <xsl:with-param name="predicate" select="$predicate"/>
	  <xsl:with-param name="subject" select="$subject"/>
	  <xsl:with-param name="object" select="concat('_:g', generate-id(.))"/>
	</xsl:call-template>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>


  <!-- nodeElement_1 - look for the type of the node -->
  <xsl:template name="nodeElement_1">
    <xsl:param name="predicate"/>
    <xsl:param name="subject"/>
    <xsl:param name="object"/>

    <!-- test type and maybe at type triple -->
    <xsl:if test="not(self::r:Description)">
      <xsl:call-template name="addTriple">
        <xsl:with-param name="predicate" select="concat('&lt;', document('')/*/namespace::r, 'type', '&gt;')"/>
        <xsl:with-param name="subject" select="$object"/>
        <xsl:with-param name="object" select="concat('&lt;', namespace-uri(), local-name(), '&gt;')"/>
      </xsl:call-template>
    </xsl:if>

    <!-- test predicate and maybe add incoming arc -->
    <xsl:if test="$predicate!='NULL'">
      <xsl:call-template name="addTriple">
        <xsl:with-param name="predicate" select="$predicate"/>
        <xsl:with-param name="subject" select="$subject"/>
        <xsl:with-param name="object" select="$object"/>
      </xsl:call-template>
    </xsl:if>

    <!-- handle propertyAttrs -->
    <xsl:for-each select="./@*">
      <xsl:if test="not((namespace-uri()='') or
                        (namespace-uri()=document('')/*/namespace::r and local-name()='RDF') or
                        (namespace-uri()=document('')/*/namespace::r and local-name()='ID') or
                        (namespace-uri()=document('')/*/namespace::r and local-name()='about') or
                        (namespace-uri()=document('')/*/namespace::r and local-name()='parseType') or
                        (namespace-uri()=document('')/*/namespace::r and local-name()='resource') or
                        (namespace-uri()=document('')/*/namespace::r and local-name()='nodeID') or
                        (namespace-uri()=document('')/*/namespace::r and local-name()='datatype') or
                        (namespace-uri()=document('')/*/namespace::r and local-name()='li') or
                        (namespace-uri()=document('')/*/namespace::r and local-name()='Description') or
                        (namespace-uri()=document('')/*/namespace::r and local-name()='aboutEach') or
                        (namespace-uri()=document('')/*/namespace::r and local-name()='aboutEachPrefix') or
                        (namespace-uri()=document('')/*/namespace::r and local-name()='bagID'))">
        <xsl:call-template name="addTriple">
          <xsl:with-param name="predicate" select="concat('&lt;', namespace-uri(), local-name(), '&gt;')"/>
          <xsl:with-param name="subject" select="$object"/>
          <xsl:with-param name="object" select="concat('&quot;', string(.), '&quot;')"/>
        </xsl:call-template>
      </xsl:if>
    </xsl:for-each>

    <!-- handle nested propertyElts -->
    <xsl:for-each select="*">
      <xsl:call-template name="propertyElt_0">
	<xsl:with-param name="subject" select="$object"/>
      </xsl:call-template>
    </xsl:for-each>

  </xsl:template>


  <!-- propertyElt - the arc name identifier element -->
  <xsl:template name="propertyElt_0">
    <xsl:param name="subject"/>
    <xsl:choose>

      <!-- parseType="Resource" implies an arc to a newly generated object
      and the nested element is a propertyElt -->
      <xsl:when test="@parseType = 'Resource'">
	<xsl:call-template name="addTriple">
	  <xsl:with-param name="predicate" select="concat('&lt;', namespace-uri(), local-name(), '&gt;')"/>
	  <xsl:with-param name="subject" select="$subject"/>
	  <xsl:with-param name="object" select="concat('_:g', generate-id(.))"/>
	</xsl:call-template>
	<xsl:call-template name="nestedPropertyElt_0">
	  <xsl:with-param name="subject" select="concat('_:g', generate-id(.))"/>
	</xsl:call-template>
      </xsl:when>

      <!-- parseType="Literal" -->
      <xsl:when test="@parseType = 'Literal'">
	<xsl:call-template name="addLiteralTriple">
	  <xsl:with-param name="predicate" select="concat('&lt;', namespace-uri(), local-name(), '&gt;')"/>
	  <xsl:with-param name="subject" select="$subject"/>
        </xsl:call-template>
      </xsl:when>

      <!-- parseType="Collection" implies an arc to a newly generated object
      and each nested element is a nodeElement -->
      <xsl:when test="@parseType = 'Collection'">
	<xsl:call-template name="addTriple">
	  <xsl:with-param name="predicate" select="concat('&lt;', namespace-uri(), local-name(), '&gt;')"/>
	  <xsl:with-param name="subject" select="$subject"/>
	  <xsl:with-param name="object" select="concat('_:g', generate-id(.))"/>
	</xsl:call-template>
	<xsl:call-template name="collection_r">
	  <xsl:with-param name="subject" select="concat('_:g', generate-id(.))"/>
	  <xsl:with-param name="index" select="1"/>
	</xsl:call-template>
      </xsl:when>

      <!-- default interpretation - expected a nested nodeElement -->
      <xsl:otherwise>
	<xsl:call-template name="nestedTypedNode_0">
	  <xsl:with-param name="predicate" select="concat('&lt;', namespace-uri(), local-name(), '&gt;')"/>
	  <xsl:with-param name="subject" select="$subject"/>
	</xsl:call-template>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>


  <!-- nestedTypedNode - call nodeElement with the sole nested element -->
  <xsl:template name="nestedTypedNode_0">
    <xsl:param name="predicate"/>
    <xsl:param name="subject"/>
    <xsl:for-each select="*">
      <xsl:call-template name="nodeElement_0">
        <xsl:with-param name="predicate" select="$predicate"/>
        <xsl:with-param name="subject" select="$subject"/>
      </xsl:call-template>
    </xsl:for-each>
  </xsl:template>


  <!-- nestedPropertyElt - call propertyElt with the sole nested element -->
  <xsl:template name="nestedPropertyElt_0">
    <xsl:param name="subject"/>
    <xsl:for-each select="*">
      <xsl:call-template name="propertyElt_0">
        <xsl:with-param name="subject" select="$subject"/>
      </xsl:call-template>
    </xsl:for-each>
  </xsl:template>


  <!-- collect - recursive function to gather elements in a parseType="Collection" -->
  <xsl:template name="collection_r">
    <xsl:param name="subject"/>
    <xsl:param name="index"/>

    <!-- first -->
    <xsl:for-each select="./*[$index]"> <!-- for-each on only one element -->
      <xsl:call-template name="nodeElement_0">
        <xsl:with-param name="predicate" select="concat('&lt;', document('')/*/namespace::r, 'first', '&gt;')"/>
        <xsl:with-param name="subject" select="$subject"/>
      </xsl:call-template>
    </xsl:for-each>

    <!-- rest -->
    <xsl:choose>
      <!-- either a nodeElement and another collection -->
      <xsl:when test="./*[$index+1]">
        <xsl:call-template name="addTriple">
          <xsl:with-param name="predicate" select="concat('&lt;', document('')/*/namespace::r, 'rest', '&gt;')"/>
          <xsl:with-param name="subject" select="$subject"/>
          <xsl:with-param name="object" select="concat('_:g', generate-id(./*[$index]))"/>
        </xsl:call-template>

        <xsl:call-template name="collection_r">
          <xsl:with-param name="subject" select="concat('_:g', generate-id(./*[$index]))"/>
          <xsl:with-param name="index" select="$index+1"/>
        </xsl:call-template>
      </xsl:when>

      <!-- or a nill signfying the end of the list -->
      <xsl:otherwise>
        <xsl:call-template name="addTriple">
          <xsl:with-param name="predicate" select="concat('&lt;', document('')/*/namespace::r, 'rest', '&gt;')"/>
          <xsl:with-param name="subject" select="concat('_:', $subject)"/>
          <xsl:with-param name="object" select="concat('&lt;', document('')/*/namespace::r, 'nil', '&gt;')"/>
        </xsl:call-template>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>


</xsl:transform>

