xsl-list
[Top] [All Lists]

Re: [xsl] counting element characters

2008-08-10 16:10:59
   <xsl:variable name="c">
           <xsl:for-each select="descendant::p">
              <xsl:value-of  select="string-length(.)"/>
           </xsl:for-each>
   </xsl:variable>
   <xsl:value-of select="sum($c/text())"/>

This is defining a variable $c of type document-node() and the
sequence constructor that produces its value produces a sequence of
text() nodes.

In any xml tree there cannot be two adjacent text nodes -- they are
merged on creating the tree.

Therefore, $c is a document-node() that has a single text node child.

$c/text()   is the total output produced by the <xsl:value-of> instruction.

The expression:
  sum($c/text())

is producing the sum of a sequence of one item and the result is
simply this same item -- the value of the $c variable (the
concatenation of all results of <xsl:value-of>)

In the case of the given source xml document:

<doc>
<a>
   <p>some text to be counted</p> <!-- 23 chars there -->
   <x>other text</x>
   <p>some more text to be counted</p> <!-- 28 chars -->
</a>
</doc>


this result is: 2328

One correct way to specify the desired processing is the following:

<xsl:template match="a">
   <xsl:variable name="c" as="text()*">
           <xsl:for-each select="descendant::p">
              <xsl:value-of  select="string-length(.)"/>
           </xsl:for-each>
   </xsl:variable>
   <xsl:value-of select="sum($c)"/>
</xsl:template>

and it produces the following result, when the template is applied on
the "a" element of the above document:

51.


Cheers,
Dimitre Novatchev



On Sun, Aug 10, 2008 at 3:17 PM, tom s <tshmit(_at_)yahoo(_dot_)com> wrote:
I'm almost as embarrassed by this question as I am baffled by it....I'd like 
to sum the number of PCDATA characters contained in specified elements. For 
example:

<doc>
<a>
   <p>some text to be counted</p> <!-- 23 chars there -->
   <x>other text</x>
   <p>some more text to be counted</p> <!-- 28 chars -->
</a>
</doc>

I'd like to calculate the sum of characters in the <p> tags; here 51.

I thought I would use something like:
<xsl:template match="a">
   <xsl:variable name="c">
           <xsl:for-each select="descendant::p">
              <xsl:value-of  select="string-length(.)"/>
           </xsl:for-each>
   </xsl:variable>
   <xsl:value-of select="sum($c/text())"/>
</xsl:template>

This seems to work in the xmlspy processor, but saxon generates values like 
3.0010118811741284E51, which is substantially more than the number of atoms 
in the universe, I think. I assume it is some sort of type problem...

Also, if it happens that <a> contains no <p> elements, saxon complains that 
it can't convert an empty string to a double. I tried conditioning the 
evaluation of the sum() on <xsl:when test="count($c/text()) > 0">, to avail.

Any help is greatly appreciated!!




--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: 
<mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--





-- 
Cheers,
Dimitre Novatchev
---------------------------------------
Truly great madness cannot be achieved without significant intelligence.
---------------------------------------
To invent, you need a good imagination and a pile of junk
-------------------------------------
Never fight an inanimate object
-------------------------------------
You've achieved success in your field when you don't know whether what
you're doing is work or play

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--

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