[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: Embedding the XPath of an input Text Fragment in

Subject: Re: 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)
Re:  Embedding the XPath of an input Text Fragment in
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

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2011 All Rights Reserved.