Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

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

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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)

>Solution :

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)
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading