They appear identical to me. Is there any difference between the two?
XML:
<?xml version="1.0" encoding="UTF-8"?>
<a>
<b>1<c>Cat</c></b>
<b>2<c>Cow</c></b>
<b>3<c>Dog</c></b>
<b></b>
<b>4<c>Fish</c></b>
<b e="9">a<f>s</f></b>
</a>
XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fn="http://www.w3.org/2005/xpath-functions">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="a/b">
<xsl:where-populated>
<xsl:value-of select="c"/>
</xsl:where-populated>
<xsl:on-non-empty>
<xsl:value-of select="c"/>
</xsl:on-non-empty>
<xsl:on-empty>EMPTY</xsl:on-empty>
</xsl:template>
</xsl:stylesheet>
Output:
<?xml version="1.0" encoding="UTF-8"?>
CatCat
CowCow
DogDog
EMPTY
FishFish
EMPTY
Also, why is the last line considered "EMPTY"?
CodePudding user response:
Have you read the explanations and examples in the spec at
https://www.w3.org/TR/xslt-30/#where-populated
https://www.w3.org/TR/xslt-30/#element-on-non-empty
?
The purpose of where-populated
is to make it easier to avoid generating something like a list or a glossary if it's going to be empty. The problem it solves is that the normal way of doing this:
<xsl:if test="exists(glossary-item)">
<glossary>
<xsl:for-each select="glossary-item">
...
</xsl:for-each>
</glossary>
</xsl:if>
isn't streamable, because it involves two passes over the glossary contents.
The on-non-empty
instruction is subtly different: it allows you to output a heading (etc) so long as it's not the only thing present. So you can write
<glossary>
<xsl:on-non-empty>
<h1>Here is the glossary</h1>
</xsl:on-non-empty>
<xsl:for-each select="glossary-item">
...
</xsl:for-each>
</glossary>
and the h1 will be omitted if no other content is generated. Again, it's provided because the usual way of writing this would involve two passes over the input.
CodePudding user response:
I don't think your sample captures the use case of these instructions, https://www.w3.org/TR/xslt-30/#where-populated-example is one where the three instructions are used together to construct content. I would say, generally the xsl:where-populated
wraps a result element container like an ol
or ul
or a table
that is only supposed to be present if there are input items that map to e.g. li
/list items or tr
/table rows.
The xsl:on-none-empty
looks at any sibling content/sequence constructors, or as the text in the spec says: "The xsl:on-non-empty
instruction is typically used to generate headers or footers appearing before or after a list of items, where the header or footer is to be omitted if there are no items in the list.".
Finally, xsl:on-empty
looks at whether "every preceding sibling instruction, text node, and literal result element in the same sequence constructor returns either an empty sequence, or a sequence consisting entirely of vacuous items", and only outputs its content in that case.