xsl-list
[Top] [All Lists]

Re: this script converts an instance path to an RNG path

2003-03-31 16:42:21
How it works ...

On Monday, March 31, 2003, at 06:02  PM, S Woodside wrote:

It's a recursive template, $fragment gets ever shorter, it pulls steps off the front of the string.

  <!-- Converts an instance path to an RNG path -->
  <xsl:template name="inst2rngPath">
    <xsl:param name="fragment"/>

fragment must be an XPath string from an instance document that conforms to a given RNG grammar

    <xsl:choose>
<xsl:when test="starts-with($fragment, '/')"> <!-- strip beginning / -->
        <xsl:call-template name="inst2rngPath">
<xsl:with-param name="fragment" select="substring-after($fragment, '/')"/>
        </xsl:call-template>
      </xsl:when>

That section eliminates any leading "/" if there is one and recurses without it.

This section inserts //*[(_at_)name=' ... (since the instance node steps are encoded into the RNG as attributes called "name"). There can be arbitrary steps inbetween name-defining nodes in RNG that might define optional, zeroOrMore, etc. so // just skips them.

<xsl:otherwise>
        <xsl:text>//*[(_at_)name='</xsl:text>

this section coming up will insert a single step in the XPath.

        <xsl:choose>
<xsl:when test="substring-before($fragment, '/')">
            <xsl:value-of select="substring-before($fragment, '/')"/>
          </xsl:when><xsl:otherwise>
            <xsl:value-of select="$fragment"/>
        </xsl:otherwise></xsl:choose>
        <xsl:text>']</xsl:text>

It used a choose because the substring-before() xpath function returns nothing if the "before" string isn't found (as opposed to returning the whole string) so that if this is the last recursive step, and there is no "/" it will just select $fragment

Now we will either recurse if there's something left to process, or stop recursing

        <xsl:choose>
<xsl:when test="contains($fragment, '/')"> <!-- recursive step -->
            <xsl:call-template name="inst2rngPath">
<xsl:with-param name="fragment" select="substring-after($fragment, '/')"/>
            </xsl:call-template>

that recursed after snipping off the first node step

          </xsl:when><xsl:otherwise>  <!-- default step -->
            <xsl:text>/*</xsl:text>
          </xsl:otherwise>

that add /* to the end to select all children (maybe not necessary though)

        </xsl:choose>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>


That's all.

simon


XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list



<Prev in Thread] Current Thread [Next in Thread>