Search code examples
xsltxpathxslt-2.0xpath-2.0

How do i select the preceding nodes of a text node starting from a specific node and not the root node?


How do i select the preceding nodes of a text node starting from a specific node whose id i know instead of getting the text nodes from the root node?

When i invoke the below piece from a template match of text node, I get all the preceding text nodes from the root. I want to modify the above piece of code to select only the text nodes that appear after the node having a specific id say 123. i.e something like //*[@id='123']

          <xsl:template match="text()[. is $text-to-split]"> 
          <xsl:variable name="split-index" as="xsd:integer" 
           select="$index - sum(preceding::text()/string-length(.))"/> 
          <xsl:value-of select="substring(., 1, $split-index - 1)"/> 
          <xsl:copy-of select="$new"/> 
          <xsl:value-of select="substring(., $split-index)"/> 
          </xsl:template> 

         <xsl:variable name="text-to-split" as="text()?" 
         select="descendant::text()[sum((preceding::text(), .)/string-length(.)) ge $index][1]"/> 

How do i include the condition in places where i use preceding::text inorder to select preceding text nodes relative to the specific node's id which i know?


Solution

  • Here are a few variants that you can use:

    <xsl:stylesheet version="2.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:strip-space elements="*"/>
     <xsl:output method="text"/>
    
     <xsl:variable name="vStart" select="/*/*[@myId='123']/text()"/>
     <xsl:variable name="vEnd" select="/*/*[last()]"/>
    
        <xsl:template match="/">
          <xsl:value-of select=
           "*/*[last()]
                 /sum(preceding::text()
                     intersect
                      $vStart/following::text()
                      )
         "/>
    ---------------
          <xsl:value-of select=
           "*/*[last()]
                 /sum(preceding::text()[. >> $vStart])
         "/>
    --------------- 
          <xsl:value-of select=
           "sum(/*/*[. >> $vStart and . &lt;&lt; $vEnd])
         "/>
        </xsl:template>
    </xsl:stylesheet>
    

    When this transformation is applied on the following XML document:

    <nums>
      <num>01</num>
      <num>02</num>
      <num>03</num>
      <num>04</num>
      <num myId='123'>05</num>
      <num>06</num>
      <num>07</num>
      <num>08</num>
      <num>09</num>
      <num>010</num>
    </nums>
    

    the desired results are produced:

    30
    ---------------
          30
    --------------- 
          30