<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
		xmlns="http://www.w3.org/1999/xhtml"
		xmlns:h="http://www.w3.org/1999/xhtml"
		xmlns:f="http://docbook.org/xslt/ns/extension"
		xmlns:t="http://docbook.org/xslt/ns/template"
		xmlns:m="http://docbook.org/xslt/ns/mode"
		xmlns:fn="http://www.w3.org/2005/04/xpath-functions"
		xmlns:db="http://docbook.org/ns/docbook"
		xmlns:xlink="http://www.w3.org/1999/xlink"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
		exclude-result-prefixes="h f m fn db t xlink xs"
                version="2.0">

<xsl:import href="/sourceforge/docbook/xsl2/html/docbook.xsl"/>

<!-- If you want to assert that your stylesheet has processing for an 
     extension, list it in the schema-extensions element, like so:

<xsl:param name="schema-extensions" as="element()*">
  <db:productlist/>
</xsl:param>
-->

<xsl:template match="/">
  <xsl:choose>
    <xsl:when test="db:map">
      <xsl:variable name="content">
	<xsl:apply-templates/>
      </xsl:variable>
      <xsl:apply-templates select="$content"/>
    </xsl:when>
    <xsl:otherwise>
	<xsl:apply-imports/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

<xsl:template match="db:map">
  <xsl:apply-templates mode="m:expandmap">
    <xsl:with-param name="base-uri" select="base-uri(.)"/>
  </xsl:apply-templates>
</xsl:template>

<xsl:template match="*" mode="m:expandmap">
  <xsl:param name="base-uri" select="''"/>

  <xsl:variable name="subtopics" select="*"/>
  <xsl:variable name="topic" select="document(@xlink:href,.)"/>

  <xsl:copy-of select="$topic/*/preceding-sibling::node()"/>
  <xsl:element name="{name($topic/*)}"
	       namespace="{namespace-uri($topic/*)}">

    <xsl:if test="$base-uri != ''">
      <xsl:attribute name="xml:base" select="$base-uri"/>
    </xsl:if>

    <xsl:copy-of select="$topic/*/@*"/>
    <xsl:copy-of select="$topic/*/node()"/>
    <xsl:apply-templates select="$subtopics" mode="m:expandmap"/>
  </xsl:element>
  <xsl:copy-of select="$topic/*/following-sibling::node()"/>
</xsl:template>

<xsl:template match="*[@conref]" mode="m:normalize">
  <xsl:variable name="element" select="f:resolve-dita-fragid(.,@conref)"/>
  <xsl:choose>
    <xsl:when test="not($element)">
      <xsl:message terminate="yes">
	<xsl:text>Reference </xsl:text>
	<xsl:value-of select="@conref"/>
	<xsl:text> does not resolve.</xsl:text>
      </xsl:message>
    </xsl:when>
    <xsl:when test="node-name(.) != node-name($element)">
      <xsl:message terminate="yes">
	<xsl:text>Reference </xsl:text>
	<xsl:value-of select="@conref"/>
	<xsl:text> points to </xsl:text>
	<xsl:value-of select="name($element)"/>
	<xsl:text> when it must point to </xsl:text>
	<xsl:value-of select="name(.)"/>
	<xsl:text>.</xsl:text>
      </xsl:message>
    </xsl:when>
    <xsl:when test="not(empty(node()))">
      <xsl:message terminate="yes">
	<xsl:text>An element with conref must be emtpy.</xsl:text>
      </xsl:message>
    </xsl:when>
    <xsl:otherwise>
      <xsl:copy>
	<xsl:copy-of
	    select="@*[namespace-uri(.) != '' or local-name(.) != 'conref']"/>
	<xsl:apply-templates select="$element/node()"/>
      </xsl:copy>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

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

<xsl:template match="db:link">
  <xsl:variable name="target"
		select="f:find-dita-fragid(root(.),
			                   substring-after(@xlink:href,'#'))"/>
  <xsl:variable name="href"
		select="if ($target)
                        then f:href(/,$target)
			else @xlink:href"/>

  <xsl:choose>
    <xsl:when test="node()">
      <a href="{$href}">
	<xsl:call-template name="class"/>
	<xsl:if test="db:alt">
	  <xsl:attribute name="title" select="db:alt[1]"/>
	</xsl:if>
	<xsl:apply-templates/>
      </a>
    </xsl:when>
    <xsl:otherwise>
      <a href="{$href}">
	<xsl:call-template name="class"/>
	<xsl:value-of select="@xlink:href"/>
      </a>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

<xsl:template match="db:xref" name="db:xref">
  <xsl:variable name="target"
		select="f:find-dita-fragid(root(.),
			                   substring-after(@xlink:href,'#'))"/>

  <xsl:if test="count($target) &gt; 1">
    <xsl:message>
      <xsl:text>Warning: the ID '</xsl:text>
      <xsl:value-of select="@linkend"/>
      <xsl:text>' is not unique.</xsl:text>
    </xsl:message>
  </xsl:if>

  <xsl:choose>
    <xsl:when test="count($target) = 0">
      <xsl:message>
        <xsl:text>XRef to nonexistent id: </xsl:text>
        <xsl:value-of select="@linkend"/>
      </xsl:message>
      <span class="formatting-error">
	<xsl:call-template name="id"/>
	<xsl:text>???</xsl:text>
      </span>
    </xsl:when>

    <xsl:when test="$target/@xreflabel">
      <a href="{f:href(/,$target)}">
	<xsl:call-template name="xreflabel">
	  <xsl:with-param name="target" select="$target"/>
	</xsl:call-template>
      </a>
    </xsl:when>

    <xsl:otherwise>
      <xsl:apply-templates select="$target" mode="m:xref-to-prefix"/>

      <a href="{f:href(/,$target)}">
	<xsl:if test="$target/db:info/db:title">
	  <xsl:attribute name="title" select="string($target/db:info/db:title)"/>
	</xsl:if>
	<xsl:apply-templates select="$target" mode="m:xref-to">
	  <xsl:with-param name="referrer" select="."/>
	  <xsl:with-param name="xrefstyle">
	    <xsl:choose>
	      <xsl:when test="@role and not(@xrefstyle)
			      and $use.role.as.xrefstyle != 0">
		<xsl:value-of select="@role"/>
	      </xsl:when>
	      <xsl:otherwise>
		<xsl:value-of select="@xrefstyle"/>
	      </xsl:otherwise>
	    </xsl:choose>
	  </xsl:with-param>
	</xsl:apply-templates>
      </a>

      <xsl:apply-templates select="$target" mode="m:xref-to-suffix"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

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

<xsl:function name="f:resolve-dita-fragid" as="element()?">
  <xsl:param name="node" as="element()"/>
  <xsl:param name="href" as="xs:string"/>

  <xsl:choose>
    <xsl:when test="starts-with($href,'#')">
      <xsl:sequence
	  select="f:find-dita-fragid(root($node),substring-after($href,'#'))"/>
    </xsl:when>
    <xsl:when test="contains($href,'#')">
      <xsl:variable name="uri" select="substring-before($href,'#')"/>
      <xsl:variable name="id" select="substring-after($href,'#')"/>
      <xsl:variable name="doc" select="document($uri, $node)"/>
      <xsl:sequence select="f:find-dita-fragid($doc,$id)"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:variable name="doc" select="document($href, $node)"/>
      <xsl:sequence select="$doc/*[1]"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:function>

<xsl:function name="f:find-dita-fragid" as="element()?">
  <xsl:param name="node" as="document-node()"/>
  <xsl:param name="ditaref" as="xs:string"/>

  <xsl:choose>
    <xsl:when test="contains($ditaref,'/')">
      <xsl:variable name="topicid" select="substring-before($ditaref,'/')"/>
      <xsl:variable name="id" select="substring-after($ditaref,'/')"/>
      <xsl:variable name="topic" select="$node/key('id', $topicid)"/>
      <xsl:sequence select="$topic//*[@xml:id=$id]"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:sequence select="$node/key('id', $ditaref)"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:function>

</xsl:stylesheet>
