Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the function of the count() in this xpath?

Tags:

xml

xslt

xpath

I saw this line of code in an implementation of the Muenchian method:

<xsl:for-each 
select="//product[count(. | key('products-by-category', @category)[1]) = 1]">

I don't get what is happening with count(). I think that count(.) means count(self::product), which is always 1, and the pipe operator (|) adds the first node that matches the key, but shouldn't the key 'products-by-category' always return a node-set, given that product has the 'category' attribute and therefore match itself?

In which elements this for-each loop iterates? Can you provide a natural language translation for this expression? Thanks.

like image 227
Federico Avatar asked Mar 18 '23 02:03

Federico


2 Answers

In XPath 1.0, the expression count($x|$y)=1 is used to test whether $x and $y are the same node. In 2.0, you can use the more intuitive expression $x is $y. It works because if both $x and $y are singleton sets, then the union of the two sets will contain two nodes if they are different, but only one if they are the same.

In this example, the expression is being used to ask "is the current node the first one with its particular key value", which is the critical test used in Muenchian grouping.

Another way of doing the same test in XPath 1.0 is the expression generate-id($x) = generate-id($y). You will see both forms used.

like image 148
Michael Kay Avatar answered Mar 23 '23 11:03

Michael Kay


Can you provide a natural language translation for this expression?

Shortly, it means "for each product that is first in its category".

How so? It takes all product elements, anywhere in your document:

<xsl:for-each select="//product">

and filters them by the expression:

[count(. | key('products-by-category', @category)[1]) = 1]

in this expression, this part:

key('products-by-category', @category)[1])

refers to the first product node in the same category as the one of the currently evaluated product.

Now, if the currently evaluated product is also the first product in its category, then counting the two together will return 1. Otherwise, there would be two distinct nodes to count, and the result would be 2.

like image 22
michael.hor257k Avatar answered Mar 23 '23 11:03

michael.hor257k