Reputation: 15475
I have a template element that is specific to listitems nodes.
xsl
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="text"/>
<xsl:template match="listitems">
<xsl:value-of select="@status" />
</xsl:template>
</xsl:stylesheet>
xml
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="callvsapply.xslt"?>
<!-- sample XML snippet -->
<xml>
<foo status="No">You are here.</foo>
<bar status="Yes">Hello Bar!</bar>
<baz status="No">Hello Baz!</baz>
<listitems status="Yes" id="13" />
<listitems status="No" id="12" />
</xml>
results
You are here.
Hello Bar!
Hello Baz!
Yes
No
Why does all text print? I expected just Yes and No.
Upvotes: 0
Views: 56
Reputation: 101728
XSLT has a concept of "built-in template rules", which are templates that are used if no relevant template is defined for the current node to which templates are being applied.
They look like this:
<xsl:template match="*|/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="text()|@*">
<xsl:value-of select="."/>
</xsl:template>
<xsl:template match="processing-instruction()|comment()"/>
What these boil down to is:
So basically, XSLT's default behavior, if no templates are specified at all, is to walk the document from top to bottom, outputting the value of all text nodes along the way. That is what you are seeing - your XSLT is outputting all text it encounters on the way down.
To remedy this in your case, there are two basic approaches:
First approach: intercept the processing at the root node (or at the document element), and directly target the nodes you want to process from there:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="text"/>
<xsl:template match="/*">
<xsl:apply-templates select="listitems" />
</xsl:template>
<xsl:template match="listitems">
<xsl:value-of select="@status" />
</xsl:template>
</xsl:stylesheet>
Second approach: override the built-in processing for text nodes, so that their values are not sent to the output by default:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="text"/>
<xsl:template match="listitems">
<xsl:value-of select="@status" />
</xsl:template>
<xsl:template match="text()" />
</xsl:stylesheet>
Upvotes: 3
Reputation: 3435
You have to first delete all elements that you don't need to print.
For this you can use this:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="text"/>
<xsl:template match="listitems">
<xsl:value-of select="@status" />
</xsl:template>
<xsl:template match="node()|@*">
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1