Subject: Re: [xsl] Embedding the XPath of an input Text Fragment in output From: Florent Georges <lists@xxxxxxxxxxxx> Date: Fri, 13 Jun 2008 13:43:51 +0200 (CEST) |
David Carlisle wrote: Hi > The schematron sources have several variants of this, targetting > different use cases. using name() is fine for human-oriented paths > in error reprorting etc By the way, the template rule for generating the paths in the Schematron skeleton, for human purpose, is: <xsl:template match="node() | @*" mode="schematron-get-full-path-2"> <!--report the element hierarchy--> <xsl:for-each select="ancestor-or-self::*"> <xsl:text>/</xsl:text> <xsl:value-of select="name(.)"/> <xsl:if test="preceding-sibling::*[name(.)=name(current())]"> <xsl:text>[</xsl:text> <xsl:value-of select=" count(preceding-sibling::*[name(.)=name(current())])+1"/> <xsl:text>]</xsl:text> </xsl:if> </xsl:for-each> <!--report the attribute--> <xsl:if test="not(self::*)"> <xsl:text/>/@<xsl:value-of select="name(.)"/> </xsl:if> </xsl:template> A few remarks. 1) The test as it is make that the first element with a particular name never has a positional predicate, and the following always have one: "elem", then "elem[2]", "elem[3]", etcetera. I would rather say that if there is only one element of a particular name, you can drop the predicate, if not you should add "[1]". 2) The test for reporting the attribute is wrong if one asks the path to something else than an element or an attribute. 3) This has been developed for XSLT 1.0 initially, but even in the XSLT 2.0 version it uses name() instead of node-name(). So for an XSLT 2.0 version, to generate paths targeted at human beings, I propose the following. Any comment? <!-- for any kind of node, report the elements path --> <xsl:template match="node() | @*" priority="-2" mode="path"> <xsl:for-each select="ancestor-or-self::*"> <xsl:text>/</xsl:text> <xsl:value-of select="name(.)"/> </xsl:for-each> </xsl:template> <!-- add a positional predicate if there are other siblings of the same name --> <xsl:template match="*" mode="path"> <xsl:next-match/> <xsl:if test=" count(../*[node-name(.) eq node-name(current())]) gt 1"> <xsl:text>[</xsl:text> <xsl:value-of select=" count(preceding-sibling::*[ node-name(.) eq node-name(current()) ]) + 1"/> <xsl:text>]</xsl:text> </xsl:if> </xsl:template> <!-- add a positional predicate if there are other siblings of the same name --> <xsl:template match="processing-instruction()" mode="path"> <xsl:next-match/> <xsl:if test="count(../processing-instruction()[ node-name(.) eq node-name(current()) ]) gt 1"> <xsl:text>[</xsl:text> <xsl:value-of select=" count(preceding-sibling::processing-instruction()[ node-name(.) eq node-name(current()) ]) + 1"/> <xsl:text>]</xsl:text> </xsl:if> </xsl:template> <!-- add the attribute step --> <xsl:template match="@*" mode="path"> <xsl:next-match/> <xsl:text>/@</xsl:text> <xsl:value-of select="name(.)"/> </xsl:template> <!-- add the string text() and maybe a positional predicate --> <xsl:template match="text()" mode="path"> <xsl:next-match/> <xsl:text>/text()</xsl:text> <xsl:if test="count(../text()) gt 1"> <xsl:text>[</xsl:text> <xsl:value-of select="count(preceding-sibling::text()) + 1"/> <xsl:text>]</xsl:text> </xsl:if> </xsl:template> <!-- add the string comment() and maybe a positional predicate --> <xsl:template match="text()" mode="path"> <xsl:next-match/> <xsl:text>/comment()</xsl:text> <xsl:if test="count(../comment()) gt 1"> <xsl:text>[</xsl:text> <xsl:value-of select=" count(preceding-sibling::comment()) + 1"/> <xsl:text>]</xsl:text> </xsl:if> </xsl:template> Regards, --drkm _____________________________________________________________________________ Envoyez avec Yahoo! Mail. Une boite mail plus intelligente http://mail.yahoo.fr
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] Embedding the XPath of an, David Carlisle | Thread | Re: [xsl] Embedding the XPath of an, David Carlisle |
Re: [xsl] Printing CDATA from feed , Joe Fawcett | Date | Re: [xsl] Embedding the XPath of an, David Carlisle |
Month |