<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="/parts/xsltdoc.xsl" type="text/xsl" media="screen"?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
  xmlns:foaf="http://xmlns.com/foaf/0.1/"
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/"
>

 <xsl:variable name="_doas" select="document('')//rdf:Description[1]"/>
 <xsl:template name="_doas_description">
  <rdf:RDF xmlns="http://purl.org/net/ns/doas#">
   <rdf:Description rdf:about="">
    <title>Comment to RDF stylesheet</title>
    <description>This is an attempt to extract RDF embedded as XHTML comment in some web pages. Not perfect, but works for many weblogs with RSS and CC metadata as comments, so long as they are well-formed (in many cases, not...)</description>
    <author rdf:parseType="Resource">
     <name>Masahide Kanzaki</name>
     <mbox rdf:resource="mailto:webmaster@kanzaki.com"/>
    </author>
    <created>2005-07-27</created>
    <release rdf:parseType="Resource">
     <revision>0.25</revision>
     <created>2005-07-27</created>
    </release>
    <rights>(c) 2005 by the author, copyleft under GPL</rights>
    <license rdf:resource="http://creativecommons.org/licenses/GPL/2.0/"/>
   </rdf:Description>
  </rdf:RDF>
 </xsl:template>

 <xsl:output indent="yes" method="xml"/>

 <xsl:template match="/">
 <!--** Starting point. Provide rdf:RDF as literal element, since each comment usually has its own rdf:RDF, resulting multiple rdf:RDF trouble. -->
  <rdf:RDF>
  <xsl:apply-templates select="//comment()"/>
  </rdf:RDF>
 </xsl:template>

 <xsl:template match="comment()">
 <!--** If a comment contains string 'rdf:RDF', normalize the space and call parseEscXml with comment body. -->
  <xsl:if test="contains(.,'rdf:RDF')">
   <xsl:call-template name="parseEscXml">
    <xsl:with-param name="str" select="normalize-space(.)"/>
    <xsl:with-param name="nest" select="0"/>
   </xsl:call-template>
  </xsl:if>
 </xsl:template>
 
 <xsl:template name="parseEscXml">
 <!--** Parse comment string and extract xml elements. Steps:-->
  <xsl:param name="str"/><!--** escaped string of RDF/XML-->
  <xsl:param name="nest"/><!--** nest level-->
  <xsl:param name="nsattr"/><!--** to declare xmlns on node element-->

  <xsl:choose>
   
   <!--@ (A) If tag found (contains '<')-->
   <xsl:when test="contains($str,'&lt;')">

   <!--@ first, output literal part (before '<')-->
    <xsl:value-of select="substring-before($str,'&lt;')"/>

   <!--@ and then get first tag part ($tag) and rest of tag ($rest). Also, find attributes part ($attr)-->
    <xsl:variable name="tag" select="substring-before(substring-after($str,'&lt;'),'&gt;')"/><!--** tag (inside <>) -->
    <xsl:variable name="rest" select="substring-after($str,'&gt;')"/><!--** rest of the input string -->
    <xsl:variable name="attr" select="substring-after($tag,' ')"/><!--** attribute part within $tag-->
  
    <xsl:choose>
    <!--@ (A-1) If tag is 'rdf:RDF', do not process (because it is provided as literal element at root) and call next parseEscXml with ns attributes -->
     <xsl:when test="substring($tag,1,7)='rdf:RDF'">
      <xsl:call-template name="parseEscXml">
       <xsl:with-param name="str" select="$rest"/>
       <xsl:with-param name="nest" select="$nest + 1"/>
       <xsl:with-param name="nsattr" select="$attr"/>
      </xsl:call-template>
     </xsl:when>
     
     <xsl:otherwise>

     <!--@ (A-2) else, test whether it is empty, end tag, or open tag, -->
      <xsl:variable name="isempty">
       <xsl:choose>
        <xsl:when test="substring($tag,string-length($tag),1)='/'">t</xsl:when>
        <xsl:otherwise>f</xsl:otherwise>
       </xsl:choose>
      </xsl:variable><!--** whether $tag is empty element -->
      <!--@ then determine tag (element) name. leave it '' if end tag.-->
      <xsl:variable name="elt">
       <xsl:choose>
        <xsl:when test="substring($tag,1,1)='/'"></xsl:when>
        <xsl:when test="contains($tag,' ')"><xsl:value-of select="substring-before($tag,' ')"/></xsl:when>
        <xsl:when test="$isempty='t'"><xsl:value-of select="substring-before($tag,'/')"/></xsl:when>
        <xsl:otherwise><xsl:value-of select="$tag"/></xsl:otherwise>
       </xsl:choose>
      </xsl:variable><!--** $tag element name -->
     
      <xsl:if test="$elt != ''">
       <!--@ If $tag is not end tag (has tag name $elt), create element node and parse attribute string .-->
       <xsl:text>
</xsl:text><xsl:element name="{$elt}">

        <xsl:call-template name="parseAttr">
         <xsl:with-param name="attrs" select="$attr"/>
        </xsl:call-template>

        <!--@ If $nsattr presents (i.e. direct children of rdf:RDF), parseAttr with $nsattr to add xmlns: decl.-->
        <xsl:if test="$nsattr !=''">
         <xsl:call-template name="parseAttr">
          <xsl:with-param name="attrs" select="$nsattr"/>
         </xsl:call-template>
        </xsl:if>
        <!--@ If Not empty element, call nesting parseEscXml with rest of string, before outputing end tag of the element. -->
        <xsl:if test="$isempty='f'">
         <xsl:call-template name="parseEscXml">
          <xsl:with-param name="str" select="$rest"/>
          <xsl:with-param name="nest" select="$nest + 1"/>
         </xsl:call-template>
        </xsl:if>
       </xsl:element>
      </xsl:if>
      
      <!--@ After closing end tag, determine how to treat rest of string -->
      <xsl:choose>
       <!--@(A-2-1) If it is end tag, do nothing. -->
       <xsl:when test="$elt=''"></xsl:when>
       <!--@(A-2-2) else if it is empty element, call next parseEscXml with whole rest of string. -->
       <xsl:when test="$isempty ='t'">
        <xsl:call-template name="parseEscXml">
         <xsl:with-param name="str" select="$rest"/>
         <xsl:with-param name="nest" select="$nest + 1"/>
         <xsl:with-param name="nsattr" select="$nsattr"/>
        </xsl:call-template>
       </xsl:when>
       <!--@(A-2-3) otherwise (has child nodes) , call next parseEscXml with after the end tag of $rest. -->
       <xsl:otherwise>
        <xsl:call-template name="parseEscXml">
         <xsl:with-param name="str" select="substring-after($rest,concat('/',$elt,'&gt;'))"/>
         <xsl:with-param name="nest" select="$nest + 1"/>
         <xsl:with-param name="nsattr" select="$nsattr"/>
        </xsl:call-template>
       </xsl:otherwise>
      </xsl:choose>
     
     </xsl:otherwise>
    </xsl:choose>

   </xsl:when>
   <!--@(B) If no tag found, just output the string.-->
   <xsl:otherwise>
    <xsl:value-of select="$str"/>
   </xsl:otherwise>
  </xsl:choose>

 </xsl:template>
 
 <xsl:template name="parseAttr">
  <!--** Parse attributes portion of string. Steps:-->
  <xsl:param name="attrs"/><!--** attributes string-->
  <!--@ Get first attribute-value-pair-like portion from $attrs. -->
  <xsl:variable name="attr">
   <xsl:choose>
    <xsl:when test="contains($attrs,'&quot; ')">
     <xsl:value-of select="substring-before($attrs,'&quot; ')"/>
    </xsl:when>
    <xsl:otherwise>
     <xsl:value-of  select="$attrs"/>
    </xsl:otherwise>
   </xsl:choose>
  </xsl:variable><!--** one attribute-value pair part to process now -->
  <xsl:variable name="rest" select="substring-after($attrs,'&quot; ')"/><!--** rest of the attributes string-->
  
  <xsl:if test="contains($attr,'=')">
   <!--@If that portion contains '=', then get attribute name and value,-->
   <xsl:variable name="n" select="substring-before($attr,'=')"/><!--** attr name-->
   <xsl:variable name="v" select="substring-after($attr,'=&quot;')"/><!--** attr value-->
   <!-- may need some restriction for xmlns: -->
   <!--@ and generate an attribute node. -->
   <xsl:attribute name="{$n}">
    <xsl:choose>
     <xsl:when test="contains($v,'&quot;')"><xsl:value-of select="substring-before($v,'&quot;')"/></xsl:when>
     <xsl:otherwise><xsl:value-of select="$v"/></xsl:otherwise>
    </xsl:choose>
   </xsl:attribute>
  </xsl:if>
  
  <!--@ If rest of attributes string is not empty, then call next parseAttr with $rest. -->
  <xsl:if test="$rest != ''">
   <xsl:call-template name="parseAttr">
    <xsl:with-param name="attrs" select="$rest"/>
   </xsl:call-template>
  </xsl:if>
 </xsl:template>
 

</xsl:stylesheet>