Search code examples
htmlxmlxpathpredicatesiblings

xPath: select a range of sibling nodes until a specific sibling node


I have the following Lis:

<ul>
    //1st subcategory with 4 sub categories        
    <li class="supercategory"></li>
      <li class="subcategory"></li>
      <li class="subcategory"></li>
      <li class="subcategory"></li>
      <li class="subcategory"></li>

    //2nd subcategory with 3 sub categories 
    <li class="supercategory"></li>
      <li class="subcategory"></li>
      <li class="subcategory"></li>
      <li class="subcategory"></li>

    //3d subcategory with 1 sub category
    <li class="supercategory"></li>
      <li class="subcategory"></li>
</ul>

I have been trying to get all the "level-2"s that come after each super category. So for the 1st supercategory the xpath match would be the 4 subcategories sibling lis and the 2nd supercategory the xpath will return 3 lis and so on.

I have tried several things but a simplistic start would be something like:

//li[@class="supercategory"][position()=2]/following-sibling::li[@class ="subcategory"]

I am trying to get the 3 subcategory lis after the 2nd supercategory but obviously this will return all lis with classes subcategory.

Thus, I am wondering if there is a predicate that would be more suited to solve this problem. Especially that in this scenario the subcategories are sibling nodes with their supercategories.

For convenience I have been testing this here: https://www.freeformatter.com/xpath-tester.html

Thanks in advance.


Solution

  • How are you using the xpath?

    If you are merely looping through the supercategories and thus know their positions and can build the xpath dynamically you can simply count the preceding subercategories.

    //li[@class="supercategory"][position()=2]/following-sibling::li[@class ="subcategory"][count(preceding-sibling::li[@class='supercategory']) = 2]