Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XSLT understand about the generate-id working way

Tags:

xslt

Further to this link xslt return selection of following siblings I Just to want to know, here, what is purpose of this generate-id and how it is making sense in this matching protocol.

<xsl:for-each select="/items/item[@lcn='005417714']">
  <xsl:for-each select="following-sibling::*[generate-id(preceding-sibling::item[@lcn != ''][1]) = generate-id(current())]">
  </xsl:for-each>
</xsl:for-each>

Any idea, pls share.

like image 254
Sakthivel Avatar asked Dec 08 '22 11:12

Sakthivel


1 Answers

The specification of generate-id is that it will always return the same ID for the same node and different IDs for different nodes. Thus, comparing the generate-id values of two nodes is the way you check whether they are the same node as opposed to just two nodes that happen to have the same value.

And current() gives you the current "top-level" context node - outside a predicate current() is the same as ., but inside a predicate expression . refers to the node the predicate is testing whereas current() still refers to the "outer .".

Now in your example

following-sibling::*[generate-id(preceding-sibling::item[@lcn != ''][1])
                      = generate-id(current())]

the outer context node is an item element (the one that the outer for-each is currently looking at). So starting from that item the expression will select:

following-sibling::*                      --- all the following sibling elements
 [                                        --- such that
  generate-id(                            --- the identity of
   preceding-sibling::item[@lcn != ''][1] --- that element's nearest preceding
                                              item with a non-empty lcn attribute
  )
  =                                       --- is the same as
  generate-id(current())                  --- the identity of the item we started
                                              with
 ]

in other words, all the sibling elements between this <item lcn="005417714"> (exclusive) and the next <item lcn="anything-non-empty"> (inclusive).

Taking an example from the linked question:

<item id="00100687" label="A/161i r" lcn="005417714" notes="A/161-182"/>
<item id="00100688" label="A/161i v" lcn="" notes=""/>
<item id="00100819" label="A/182ii v" lcn="" notes=""/>
<item id="00100820" label="A/182iii r" lcn="" notes=""/>
<item id="00100821" label="A/182iii v" lcn="" notes=""/>
<item id="00100822" label="A/183i r" lcn="005417715" notes="A/183-218"/>
<item id="00100823" label="A/183i v" lcn="" notes=""/>
<item id="00100975" label="A/216iii r" lcn="" notes=""/>

if the current context node is the item with id="00100687" then that select would pull out items 00100688, 00100819, 00100820, 00100821 and 00100822. If you wanted to exclude 00100822 you'd have to add another predicate

following-sibling::*[@lcn = '']
                    [generate-id(preceding-sibling::item[@lcn != ''][1])
                      = generate-id(current())]
like image 70
Ian Roberts Avatar answered Jan 22 '23 10:01

Ian Roberts