MrD at KookerellaLtd
MrD at KookerellaLtd

Reputation: 2807

get following sibling in sequence of orphan elements (or elements of unknown parentage)

consider (hand written code so excuse any accidents)

<xsl:variable name="foo" as="document-node()">
   <xsl:document>
      <foo1>
      <foo2>
      <foo3>
   </xsl:document>
</xsl:variable>

<xsl:variable name="foos" select="$foo/*"/>
<xsl:variable name="isItFoo3" select="$foos[2]::following-sibling"/>
 

and isItFoo3 is <foo3>

nice

but this

<xsl:variable name="foos" as="element()*">
   <foo1>
   <foo2>
   <foo3>
</xsl:variable>

<xsl:variable name="isItFoo3" select="$foos[2]::following-sibling"/>

results in empty

so, I'm assuming that following sibling requires a parent (by definition!) and literal elements in my 2nd example are orphaned in some sense, so they arent siblings.

This makes axes a little subtle, if I want to process (effectively get the 'tail') of a sequence, I need to ensure that all elements have a parent and share the same parent.

fair enough, that makes logical sense.

but then how do I get the tail (following-siblings) in a sequence when I'm not sure of the parentage of the elements?

(ok, I can explicitly copy them into a new document to make sure, but thats a little onerous, in terms of code and performance)

Upvotes: 0

Views: 33

Answers (1)

Martin Honnen
Martin Honnen

Reputation: 167716

So you can do e.g.

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="3.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="#all">
  
  <xsl:variable name="foos" as="element()*">
     <foo1/>
     <foo2/>
     <foo3/>
     <foo4/>
  </xsl:variable>
  
  <xsl:variable name="foo2" select="$foos[2]"/>
  
  <xsl:variable name="foos-after-foo2" select="let $pos := index-of($foos!generate-id(), generate-id($foo2)) return $foos[position() gt $pos]"/>

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/" name="xsl:initial-template">
    <xsl:sequence select="$foos-after-foo2"/>
  </xsl:template>

</xsl:stylesheet>

I think it can be expressed more compactly in XPath/XSLT 4, currently (still work in progress, I use XQuery syntax for the variable assignment)

let $foos := (<foo1/>, <foo2/>, <foo3/>, <foo4/>),
    $foo2 := $foos[2],
    $pos := index-where($foos, fn { . is $foo2 })
return $foos[position() gt $pos]

or as

let $foos := (<foo1/>, <foo2/>, <foo3/>, <foo4/>),
    $foo2 := $foos[2]
return subsequence($foos, index-where($foos, fn { . is $foo2 }) + 1)

Upvotes: 0

Related Questions