views:

75

answers:

2

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?

+1  A: 

In XPath 2.0, you can use operators << and >> to compare node ordering. For example:

preceding-sibling::text()[. >> $foo]

would select all sibling text nodes preceding the current one, which follow the node $foo in document order. Of course, you can use an expression instead of $foo - in your case, //*[@id='123'] - though binding it to the variable and then using that in the filter might be easier for the XSLT processor to optimize.

See this for the detailed specification of these operators.

Pavel Minaev
Thanks it works.
Rachel
I used normalize-space() while i find the length of the text content so that no additional spaces between the tags are counted but if i have tab spaces in the xhtml it is getting counted. How do i ignore it. It gets counted even if i use strip space. Just like how i added a predicate to normalize space can i add a predicate to ignore the tab space too, while i count the length of the text content. How can it be done?
Rachel
Can you give sample XML input that exposes your problem, and highlight the whitespace nodes that you want to be stripped?
Pavel Minaev
+1  A: 

Here are a few variants that you can use:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
 <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
Dimitre Novatchev
Thats great. Thanks. I used normalize-space() while i find the length of the text content so that no additional spaces between the tags are counted but if i have tab spaces in the xhtml it is getting counted. How do i ignore it. It gets counted even if i use strip space. Just like how i added a predicate to normalize space can i add a predicate to ignore the tab space too, while i count the length of the text content. How can it be done?
Rachel
@Rachel: Use: `translate($yourText,' `,'')
Dimitre Novatchev