MrD at KookerellaLtd
MrD at KookerellaLtd

Reputation: 2807

Is there a way to match "Empty" sequences/nodesets

Every now and then I want to match missing elements, i.e. an empty sequence/nodeset

(this is completely untested/run...its just for illustation and could be any XSLT version)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="/">
       <xsl:apply-templates select="stuff/SomeStuff"/>
       <xsl:if test="count(stuff/SomeStuff) = 0">
          <xsl:call-template name="noStuff"/>
       </xsl:if>
    </xsl:template>

   <xsl:template name="noStuff">
      <bar/>>
   </xsl:template>

   <xsl:template match="SomeStuff">
      <foo/>
   </xsl:template>
</xsl:stylesheet>

bit clumsy, be quite nice to go something like

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="/">
       <xsl:apply-templates select="stuff/SomeStuff"/>
    </xsl:template>

   <xsl:template match="Empty(SomeStuff)">
      <bar/>>
   </xsl:template>

   <xsl:template match="SomeStuff">
      <foo/>
   </xsl:template>
</xsl:stylesheet>

is this lurking somewhere i can't find? I think an empty sequence is 'special' enough to have something. In a functional language the sequence would exist as a datatype you could match directly on, so it feels missing to me, a bit like matching Some/None on an Option/Maybe.

Upvotes: 0

Views: 69

Answers (3)

Michael Kay
Michael Kay

Reputation: 163625

XSLT 3.0 has an instruction xsl:on-empty allowing

<xsl:template match="/">
   <xsl:apply-templates select="stuff/SomeStuff"/>
   <xsl:on-empty>
      <xsl:call-template name="noStuff"/>
   </xsl:on-empty>
</xsl:template>

The semantics aren't quite the same: this is testing that the output of the apply-templates is empty, not that its input is empty.

The drafts for XSLT 4.0 have an otherwise operator, allowing

<xsl:variable name="noStuff" as="element()">
  <noStuff/>
</xsl:variable>
...
   <xsl:apply-templates select="stuff/SomeStuff otherwise $noStuff"/>
...
<xsl:template match="noStuff">
  ...
</xsl:template>

Upvotes: 1

MrD at KookerellaLtd
MrD at KookerellaLtd

Reputation: 2807

So based on sebastiens comment

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
   <xsl:output method="xml" indent="yes"/>

   <xsl:template match="/">
      <xsl:apply-templates select="stuff"/>
   </xsl:template>

   <xsl:template match="stuff[not(SomeStuff)]" priority="1">
      <bar/>>
   </xsl:template>

   <xsl:template match="stuff">
      <xsl:apply-templates select="SomeStuff"/>
   </xsl:template>
   
   <xsl:template match="SomeStuff">
      <foo/>
   </xsl:template>
</xsl:stylesheet>

which to be fair, matches how you would do it in a FPL.

having actually written the code in a proper context, its actually quite verbose in anything but a trivial context, because you have to pass all the parameters through - in most FPs these would be 'captured' as the match would be inside the calling code.

It IS the sensible answer, just not as cost free as hoped.

Upvotes: 0

Sebastien
Sebastien

Reputation: 2714

You could use something like : stuff[not(SomeStuff)]

Example :

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
   <xsl:output method="xml" indent="yes"/>

   <xsl:template match="/">
      <xsl:apply-templates select="stuff"/>
   </xsl:template>

   <xsl:template match="stuff[not(SomeStuff)]">
      <bar/>>
   </xsl:template>

   <xsl:template match="stuff">
      <xsl:apply-templates select="SomeStuff"/>
   </xsl:template>
   
   <xsl:template match="SomeStuff">
      <foo/>
   </xsl:template>
</xsl:stylesheet>

Upvotes: 0

Related Questions