.Net application development specialists
asp.net, c#, vb.net, html, javascript, jquery, html, xhtml, css, oop, design patterns, sql server, mvc and much more
contact: admin@paxium.co.uk

Paxium is the company owned by myself, Dave Amour and used for providing IT contract development services including


  • Application development - Desktop, Web, Services - with Classic ASP, Asp.net WebForms, Asp.net MVC, Asp.net Core
  • Html, Css, JavaScript, jQuery, React, C#, SQL Server, Ado.net, Entity Framework, NHibernate, TDD, WebApi, GIT, IIS
  • Database schema design, implementation & ETL activities
  • Website design and hosting including email hosting
  • Training - typically one to one sessions
  • Reverse Engineering and documentation of undocumented systems
  • Code Reviews
  • Performance Tuning
  • Located in Cannock, Staffordshire
Rugeley Chess Club Buying Butler Cuckooland Katmaid Pet Sitting Services Roland Garros 60 60 Golf cement Technical Conformity Goofy MaggieBears Vacc Track Find Your Smart Phone eBate Taylors Poultry Services Lafarge Rebates System Codemasters Grid Game eBate DOFF

XSLT following-sibling

Contrary to what you might instinctivley believe, using the following-sibbling:: axis in XSLT does not give you the following sibling. It does in fact give you all the following siblings!

We can prove this be looking at an example. Suppose we have the following xml document:

<?xml version="1.0" encoding="UTF-8"?>
      <People>
            <Person id="1">
                  <Firstname>Dave</Firstname>
                  <Surname>Amour</Surname>
                  <Age>39</Age>
            </Person>
            <Person id="2">
                  <Firstname>Fred</Firstname>
                  <Surname>Bloggs</Surname>
                  <Age>32</Age>
            </Person>
            <Person id="3">
                  <Firstname>Tiffany</Firstname>
                  <Surname>Gallagher</Surname>
                  <Age>31</Age>
            </Person>
            <Person id="4">
                  <Firstname>Will</Firstname>
                  <Surname>Green</Surname>
                  <Age>51</Age>
            </Person>
            <Person id="5">
                  <Firstname>Hilary</Firstname>
                  <Surname>Bloggs</Surname>
                  <Age>28</Age>
            </Person>
      </People>


We will now transform this with some xslt which will attempt to select all People who have a following sibling of Will. Now if this was to evaluate to just the 1 following sibling then we would expect to see just Tiffany. The results we actually get though are Dave Fred And Tiffany. Here is our XSLT: 

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output method="html" encoding="UTF-8" indent="yes"/>
 
      <xsl:template match="//Person[following-sibling::Person/Firstname = 'Will']">
            <xsl:value-of select="Firstname"></xsl:value-of><br/><br/>
      </xsl:template>
 
      <xsl:template match="text()"></xsl:template>
</xsl:stylesheet>
 


This gives us the following results:

Dave<br /><br /> Fred<br /><br /> Tiffany<br /><br />

So this proves that following sibling gives us all following siblings, not just the next one.

Important!

Now the above example also shows something very important. When we use the = operator with a collection of nodes it returns true if the single entity exists anywhere within the collection which of course makes sense if you back and look at the results of the previous example. We can also prove this with the following experiment,

      <?xml version="1.0" encoding="UTF-8"?>
      <?xml-stylesheet type="text/xsl" href="People.xslt"?>
      <People>
            <Person id="1">
                  <Firstname>Dave</Firstname>
                  <Surname>Amour</Surname>
                  <Age>39</Age>
            </Person>
            <Person id="2">
                  <Firstname>Fred</Firstname>
                  <Surname>Bloggs</Surname>
                  <Age>32</Age>
            </Person>
            <Person id="3">
                  <Firstname>Tiffany</Firstname>
                  <Surname>Gallagher</Surname>
                  <Age>31</Age>
            </Person>
            <Person id="4">
                  <Firstname>Will</Firstname>
                  <Surname>Green</Surname>
                  <Age>51</Age>
            </Person>
            <Person id="5">
                  <Firstname>Hilary</Firstname>
                  <Surname>Bloggs</Surname>
                  <Age>28</Age>
            </Person>
            <Person id="6">
                  <Firstname>Fred</Firstname>
                  <Surname>Green</Surname>
                  <Age>22</Age>
            </Person>
            </People>
 
      <?xml version="1.0" encoding="UTF-8"?>
      <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
            <xsl:output method="html" encoding="UTF-8" indent="yes"/>
 
            <xsl:template match="/">
                  <h1>Experiment</h1>
 
                  <xsl:variable name="People" select="//Person/Firstname"></xsl:variable>
 
                  <xsl:if test="'Tiffany' = $People">
                        Tiffany exists in People
                  </xsl:if>
 
                  <p>
                        People are as follows
                  </p>
 
                  <xsl:for-each select="$People">
                        <xsl:value-of select="."></xsl:value-of><br/>
                  </xsl:for-each>
            </xsl:template>
      </xsl:stylesheet>


The above transformation gives us the following results proving the theory on how = works:

Experiment

Tiffany exists in Pepole

People are as follows

Dave
Fred
Tiffany
Will
Hilary
Fred
 


It is of course possible to specify just the preceeding sibling - by using an index. If we change our template code as follows:

      <xsl:template match="//Person[following-sibling::Person[1]/Firstname = 'Will']">
            <xsl:value-of select="Firstname"></xsl:value-of><br/><br/>
      </xsl:template>

Then we just get Tiffany as our output. If we changed it to 2 we would get Fred and 3 would give us Dave. We can see therefore that the index collection (for want of a better expression) is like an array with the items in order of proximity to the original node. You can test this by performing the mirror image function and using preceding-sibling as follows:

      <xsl:template match="//Person[preceding-sibling::Person/Firstname = 'Fred']">

            <xsl:value-of select="Firstname"></xsl:value-of><br /><br />

      </xsl:template>


In laymans terms this is saying select all People whose preceding person is Fred. This should and does give us Tiffany, Will and Hilary. Now to test our array proximity theory we should get 1 for Tiffany, 2 for Will and 3 for Hilary. You can try this yourself and see that it does work.

One other point really worth noting is that we have to specify what the sibling is ie we had to but the word Person after the ::