Output Context Node (full path) in XSLT 1.0?

匿名 (未验证) 提交于 2019-12-03 03:03:02

问题:

For debugging purposes it would be handy to output the full path of the context node from within a template, is there unabbreviated xpath or function to report this ?

Example Template:

<xsl:template match="@first">         <tr>             <td>                 <xsl:value-of select="??WHAT TO PUT IN HERE??"/>             </td>         </tr> </xsl:template> 

Example (Abridged) input document:

<people> <person> <name first="alan"> ... 

The output from the template would be something like:

people / person / name / @first  

Or something similar.

回答1:

This transformation produces an XPath expression for the wanted node:

<xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">  <xsl:output method="text"/>  <xsl:strip-space elements="*"/>      <xsl:template match="/">         <xsl:variable name="vNode" select=         "/*/*[2]/*/@first"/>         <xsl:apply-templates select="$vNode" mode="path"/>     </xsl:template>      <xsl:template match="*" mode="path">         <xsl:value-of select="concat('/',name())"/>         <xsl:variable name="vnumPrecSiblings" select=         "count(preceding-sibling::*[name()=name(current())])"/>         <xsl:variable name="vnumFollSiblings" select=         "count(following-sibling::*[name()=name(current())])"/>         <xsl:if test="$vnumPrecSiblings or $vnumFollSiblings">             <xsl:value-of select=             "concat('[', $vnumPrecSiblings +1, ']')"/>         </xsl:if>     </xsl:template>      <xsl:template match="@*" mode="path">      <xsl:apply-templates select="ancestor::*" mode="path"/>      <xsl:value-of select="concat('/@', name())"/>     </xsl:template> </xsl:stylesheet> 

when applied on the following XML document:

<people>  <person>   <name first="betty" last="jones"/>  </person>  <person>   <name first="alan" last="smith"/>  </person> </people> 

the wanted, correct result is produced:

/people/person[2]/name/@first 


回答2:

Here's a stylesheet (of dubious value) that prints the path to every element and attribute in a document:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">     <xsl:output method="text" />     <xsl:strip-space elements="*" />     <xsl:template match="*">         <xsl:param name="pathToHere" select="''" />         <xsl:variable name="precSiblings"             select="count(preceding-sibling::*[name()=name(current())])" />         <xsl:variable name="follSiblings"             select="count(following-sibling::*[name()=name(current())])" />         <xsl:variable name="fullPath"             select="concat($pathToHere, '/', name(),                 substring(concat('[', $precSiblings + 1, ']'),                      1 div ($follSiblings or $precSiblings)))" />         <xsl:value-of select="concat($fullPath, '&#xA;')" />         <xsl:apply-templates select="@*|*">             <xsl:with-param name="pathToHere" select="$fullPath" />         </xsl:apply-templates>     </xsl:template>     <xsl:template match="@*">         <xsl:param name="pathToHere" select="''" />         <xsl:value-of select="concat($pathToHere, '/@', name(),  '&#xA;')" />     </xsl:template> </xsl:stylesheet> 

When applied to this input:

<people>     <person>         <name first="betty" last="jones" />     </person>     <person>         <name first="alan" last="smith" />     </person>     <singleElement /> </people> 

Produces:

/people /people/person[1] /people/person[1]/name /people/person[1]/name/@first /people/person[1]/name/@last /people/person[2] /people/person[2]/name /people/person[2]/name/@first /people/person[2]/name/@last /people/singleElement 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!