<!DOCTYPE xsl:stylesheet [ 
  <!ENTITY LF "<xsl:text>&#10;</xsl:text>"> 
]>
<!-- func:node-kind(): EXSLT version of XPath2 function fn:node-kind() -->
<?demoProcessingInstruction?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:func="http://exslt.org/functions"
  xmlns:fn="http://www.w3.org/2005/xpath-functions"
>
  <xsl:output method="text"/>

  <func:function name="fn:node-kind">
    <xsl:param name="v" select="/.."/>

    <func:result>
      <xsl:choose>
        <xsl:when test="$v/self::text()">text</xsl:when>
        <xsl:when test="$v/self::comment()">comment</xsl:when>
        <xsl:when test="not($v/..)">document</xsl:when>
        <xsl:when 
          test="$v/self::processing-instruction()">
          <xsl:text>processing-instruction</xsl:text>
        </xsl:when>
        <xsl:when 
          test="count($v | $v/../attribute::*) = count($v/../attribute::*)">
          <xsl:text>attribute</xsl:text>
        </xsl:when>
        <xsl:when 
          test="count($v | $v/../namespace::*) = count($v/../namespace::*)">
          <xsl:text>namespace</xsl:text>
        </xsl:when>
        <xsl:otherwise>element</xsl:otherwise>
      </xsl:choose>
    </func:result>
  </func:function>

  <xsl:template match="/">
    <xsl:variable name="doc" select="document('')"/>

    <xsl:value-of select="fn:node-kind( $doc )"/>&LF;
    <xsl:value-of select="fn:node-kind( $doc/xsl:stylesheet )"/>&LF;
    <xsl:value-of select="fn:node-kind( $doc/xsl:stylesheet/@version )"/>&LF;
    <xsl:value-of select="fn:node-kind( $doc//xsl:otherwise/text() )"/>&LF;
    <xsl:value-of 
      select="fn:node-kind( ($doc/xsl:stylesheet/namespace::*)[1] )"/>&LF;
    <xsl:value-of select="fn:node-kind( $doc/processing-instruction() )"/>&LF;
    <xsl:value-of select="fn:node-kind( $doc/comment() )"/>&LF;
  </xsl:template>
</xsl:stylesheet>