You need the path to your current node—the XPath—to output it as debugging information.
The DocBook XSL stylesheet offers the
xpath.location
template for this purpose.
To output the current XPath, use the following procedure:
If you need the XPath for a different node, extend the previous code:
<xsl:message>
<xsl:text>Current XPath: </xsl:text>
<xsl:call-template name="xpath.location">
<xsl:with-param name="node" select="YOUR_XPath_Expression
"/>
</xsl:call-template>
</xsl:message>
Currently, the template in lib/lib.xsl
is
limited: it walks from the current node up to the root node and
outputs just the element name. No namespace prefixes, no
predicates. If you have a DocBook document with different
namespaces, the original version does not help.
In Example 2.3, “Namespace-aware Output of an XPath”, the revised template recognizes namespaces and counts elements on the sibling axis.
<xsl:stylesheet version="1.0" xmlns:n="urn:x-toms:ns:namespaces" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="n"> <namespaces xmlns="urn:x-toms:ns:namespaces"> <ns prefix="d">http://docbook.org/ns/docbook</ns> <ns prefix="xi">http://www.w3.org/2001/XInclude</ns> <ns prefix="rdf">http://www.w3.org/1999/02/22-rdf-syntax-ns#</ns> <ns prefix="cc">http://creativecommons.org/ns#</ns> <ns prefix="svg">http://www.w3.org/2000/svg</ns> </namespaces> <xsl:variable name="nsnodes" select="document('')//n:namespaces/n:ns"/> <xsl:template name="xpath.location"> <xsl:param name="node" select="."/> <xsl:param name="path" select="''"/> <xsl:param name="method">prefix</xsl:param> <xsl:variable name="next.path"> <xsl:choose> <xsl:when test="$method = 'prefix' and $nsnodes[namespace-uri($node)]"> <xsl:value-of select="concat($nsnodes[namespace-uri($node) = .]/@prefix, ':')"/> </xsl:when> <xsl:when test="$method = 'clark' and namespace-uri($node) != ''"> <xsl:value-of select="concat('{', namespace-uri($node), '}')"/> </xsl:when> </xsl:choose> <xsl:value-of select="local-name($node)"/> <xsl:if test="generate-id($node) != generate-id(/*) and count(../*[local-name()=local-name(current()) and namespace-uri()=namespace-uri(current())]) > 1"> <xsl:text>[</xsl:text> <xsl:value-of select="count(preceding-sibling::* [local-name()=local-name(current()) and namespace-uri()=namespace-uri(current())]) + 1"/> <xsl:text>]</xsl:text> </xsl:if> <xsl:if test="$path != ''"> <xsl:text>/</xsl:text> </xsl:if> <xsl:value-of select="$path"/> </xsl:variable> <xsl:choose> <xsl:when test="$node/parent::*"> <xsl:call-template name="xpath.location"> <xsl:with-param name="node" select="$node/parent::*"/> <xsl:with-param name="path" select="$next.path"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="concat('/', $next.path)"/> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet>
Contains the list of namespaces and their prefixes | |
Create a node set of all namespace to prefix mappings | |
Defines the method how prefixes are displayed. You can choose between “prefix” and the Clark notation. The latter adds the namespace in curly braces before the element name, but makes the whole XPath very verbose. | |
Choose between the prefixed or Clark notation | |
Checks, if we are not at the root node and there is more than one element with the same name and the same namespace. If this is true, we output a predicate where the current number is enclosed in square brackets. |
The template can output the XPath in two different notations:
method="prefix"
, default)Namespace nodes are abbreviated with a prefix. The
prefix is definied in the namespaces
element. A
XPath to the first chapter inside a book looks like this:
/d:book/d:chapter[1]
method="clark"
)Namespace nodes are printed with the full namespace
URL. The namespace URL is definied in the
namespaces
element. An XPath to the first
chapter inside a book looks like this:
/{http://docbook.org/ns/docbook}book/{http://docbook.org/ns/docbook}chapter[1]
The above notation is called the Clark notation, after JamesClark, the editor of the XSLT 1.0 and XPath 1.0 specifications. However, this notation cannot be used in XSLT as it is not officially supported. Only use the prefixed version in this case. The Clark notation is just useful for debugging purposes when you want or need the full namespace URLs.
Be aware, the previous template is slower than the original version (it has to count a little bit more). For debugging purpose it is probably fine.
http://docbook.sourceforge.net/release/xsl/current/doc/lib/xpath.location.html
A recursive solution, considering also attribute, text, and processing instruction nodes: http://www.dpawson.co.uk/xsl/sect2/xpath.html#d11572e154
Project@GitHub | Issue#7 |