Node Counting Problems

P

parksch2

I've spent quite a bit of time (way more than I'd like) today looking
for an answer to what I thought would be a simple question. I simply
need to get the count of items within some nodes up to the current node
(previous or previous-sibling related). For example, here is some
sample XML I have to work with:

<ITEM>
<CHILD>
<ITEM>
<CHILD />
<CHILD />
</ITEM>
<ITEM>
<CHILD />
<CHILD />
<CHILD />
</ITEM>
<ITEM>
<CHILD /> <<-- current node
</ITEM>
<ITEM>
<CHILD />
</ITEM>
</CHILD>
</ITEM>

Let's say the current node is as noted above. How do I get the count of
the previous CHILD nodes? In this case the number I'm looking for is 5.
Any help would be greatly appreciated!
 
D

David Carlisle

count(preceding-sibling::CHILD) + count(../preceding-sibling::ITEM/CHILD)

David
 
P

parksch2

Hey,

Serious thanks for the fast reply. For some reason
"count(../preceding-sibling::ITEM/CHILD)" returns 0 and my count starts
over every time the template executes. Also, will this example work
only if the current node was the 3rd node or will it work at anytime in
the set?
 
D

David Carlisle

"count(../preceding-sibling::ITEM/CHILD)" returns 0 `
Then your structure isn't as you showed.
Also, will this example work only if the current node was the 3rd node o
as you can see there is nothing special about 3 in teh expression it
will work on any node.

Your description was a little vague, I see someone else suggested
count(preceding::CHILD)
which might also be what you want (although it won't in general give the
same answer as the expression I gave).

David
 
P

parksch2

Hi David,

You are correct in that I provided a slightly incorrect XML example.
Sorry. Your example works perfectly with the sample I originally
posted. For some reason I can't seem to get it working on my actual XML
though. I tried playing around with the statement but I still can't get
it working. Can you please help me with the same statement for the
following XML?

<?xml version="1.0" encoding="UTF-8"?>
<MENU>
<ITEM>
<MENU>
<ITEM />
<ITEM />
<ITEM />
<ITEM />
</MENU>
</ITEM>
<ITEM>
<MENU>
<ITEM />
<ITEM />
<ITEM />
</MENU>
</ITEM>
<ITEM>
<MENU>
<ITEM />
</MENU>
</ITEM>
<ITEM>
<MENU>
<ITEM />
<ITEM />
<ITEM />
<ITEM />
</MENU>
</ITEM>
</MENU>
 
P

parksch2

Hi David,

You are correct in that I provided a slightly incorrect XML example.
Sorry. Your example works perfectly with the sample I originally
posted. For some reason I can't seem to get it working on my actual XML
though. I tried playing around with the statement but I still can't get
it working. Can you please help me with the same statement for the
following XML?

<?xml version="1.0" encoding="UTF-8"?>
<ITEM>
<CHILD>
<ITEM>
<CHILD />
<CHILD />
<CHILD />
<CHILD />
</ITEM>
</CHILD>
<CHILD>
<ITEM>
<CHILD />
<CHILD />
<CHILD />
</ITEM>
</CHILD>
<CHILD>
<ITEM>
<CHILD />
</ITEM>
</CHILD>
<CHILD>
<ITEM>
<CHILD />
<CHILD />
<CHILD />
<CHILD />
</ITEM>
</CHILD>
</ITEM>
 
P

parksch2

Hi Paul,

For some reason this returns an extremely large number. Maybe because
there are parent nodes named the same?
 
D

David Carlisle

<ITEM>
<MENU>
<ITEM />
<ITEM />
<ITEM />
<ITEM />
</MENU>
</ITEM>
<ITEM>
<MENU>
<ITEM />
<ITEM />
<ITEM />
</MENU>
</ITEM>
<ITEM>



so, the ITEM's you want to count (the leaf ones) are second cousins not
first cousins:


count(../preceding-sibling::ITEM) + count(../../preceding-sibling::ITEM/MENU/ITEM)


Or if all this going up and down is too tiresome (and you are doing this
in xslt not in some Xpath-API) you could just use

<xsl:number level="any" count="ITEM[not(*)]"/>

which will generate a running count of all the leaf ITEM nodes to the
current position.


David
 
P

parksch2

David,

count(../preceding-sibling::ITEM) +
count(../../preceding-sibling::ITEM/MENU/ITEM)

Perfect! Thanks so much! One last question:

Let's say I would now like to count the same ITEM nodes, but this time
only count the ITEM nodes that have MENU/ITEM children themselves. I
tried this and it doesn't work:

count(../preceding-sibling::ITEM/MENU/ITEM) +
count(../../preceding-sibling::ITEM/MENU/ITEM/MENU/ITEM)

Again, thanks so much for your help!
 
D

David Carlisle

Let's say I would now like to count the same ITEM nodes, but this time
only count the ITEM nodes that have MENU/ITEM children themselves. I
tried this and it doesn't work:

count(../preceding-sibling::ITEM/MENU/ITEM) +
count(../../preceding-sibling::ITEM/MENU/ITEM/MENU/ITEM)


/ selects (using the child axis) so
.../preceding-sibling::ITEM/MENU/ITEM
is not the number of items that have ITEM grandchildren, it is the
number of ITEM grandchildren.

"that have" is written "[" in Xpath so you want

count(../preceding-sibling::ITEM[MENU/ITEM]) +
count(../../preceding-sibling::ITEM/MENU[ITEM/MENU/ITEM])

David
 
P

parksch2

Hmmm, it returns the same number as before, which doesn't make sense.
It seems as if your example should work, but for some reason it
doesn't take into account the [MENU/ITEM], it just counts the ITEM
nodes again.

Any ideas?
 
P

parksch2

Here is example XML for this problem:

<MENU>
<ITEM>
<MENU>
<ITEM>
<MENU>
<ITEM/>
<ITEM/>
<ITEM/>
</MENU>
</ITEM>
<ITEM/>
<ITEM>
<MENU>
<ITEM/>
<ITEM/>
</MENU>
</ITEM>
<ITEM/> <<--current node
</MENU>
</ITEM>
</MENU>

So from the current node, I'd want it to return 2, meaning 2 ITEM nodes
before it contained MENU/ITEM...
 
D

David Carlisle

t seems as if your example should work, but for some reason it
doesn't take into account the [MENU/ITEM], it just counts the ITEM
nodes again.

Any ideas?


the nodes selected by foo and foo[MENU/ITEM] will be different (and so
the count() will be different) unless all the foo nodes have MENU/ITEM
children so if you don't see a difference, you didn't do what you think
you did.

David
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,756
Messages
2,569,540
Members
45,025
Latest member
KetoRushACVFitness

Latest Threads

Top