Search code examples
xsltumbraco

XSLT Get All Nodes where parent node is not type


I have a structure similar to as follows:

<list>
   <newsItem title="Item1"></newsItem>
   <newsItem title="Item2"></newsItem>
   <newsItem title="Item3"></newsItem>
   <newsItem title="Item4"></newsItem>
   <newsItemCategory title="Cat1">
          <newsItem title="Item1"></newsItem>
          <newsItem title="Item2"></newsItem>
          <newsItem title="Item3"></newsItem>
          <newsItem title="Item4"></newsItem>
   </newsItemCategory>
   <newsItem title="Item5"></newsItem>
   <newsItem title="Item6"></newsItem>
</list>

I am doing a for-each loop and I want all nodes of type newsItem or newsItemCateogory but I don't want to bring back newsItems that are within a newsItemCategory.

to get everything my XSLT is doing the following:

$currentPage/ancestor-or-self::root//* [name() = "newsItem" or name() = "newsItemCategory"]

I am trying to filter this:

  $currentPage/ancestor-or-self::root//* [parent::node/name() != "newsItemCategory" and (name() = "newsItem" or name() = "newsItemCategory")]

I don't know if this is the right syntax or if it's possible, but it is not bringing back the results I am looking for.


Solution

  • You can use the parent:: and self:: axes without having to resort to name() checks.

    $currentPage/ancestor-or-self::*[last()]//*[
        self::newsItem or self::newsItemCategory
    ]
    

    and I recommend using not() over !=:

    $currentPage/ancestor-or-self::*[last()]//*[
        (self:newsItem or self::newsItemCategory) and not(parent::newsItemCategory)
    ]
    

    I'm using ancestor-or-self::*[last()] to get to the top-most element in a generic way, because ancestor-or-self::root potentially selects more than one element. I don't know how Umbraco templates look like and if this really can happen or not.