how to re-number filtered elements in result set
XML:
<?xml version="1.0" encoding="utf-8"?>
<book>
<chapter>
<section name="a">...</section>
<section name="b">...</section>
<section name="c">...</section>
<section name="d">...</section>
<section name="e">...</section>
...
</chapter>
<appendix>
<section name="reference">...</section>
</appendix>
</book>
Hi, I want to output all the sections
under chapter
and appendix
nodes. The sections under appendix will be printed out definitely. But not all sections under chapter are allowed to print out, they depend on some external condition (if the section name is in allowed list which passed in from java application).
Also sections
under chapter
should be output with correct sequence number before section name which looks like the following:
Desired result
- b ...
- d ...
(which means section a, c, e are filtered out)
My question is how I can produce the above desired output for //chapter/section
? Any hints or help is highly appreciated
My XSL:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ex="http://example.com/namespace" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:param name="validChapters" />
<xsl:function name="ex:isValidChapter" as="xs:boolean">
<xsl:param name="str-in" as="xs:string"/>
<xsl:choose>
<xsl:when test="contains($validChapters, $str-in)">
<xsl:sequence select="true()" />
</xsl:when>
<xsl:otherwise>
<xsl:sequence select="false()" />
</xsl:otherwise>
</xsl:choose>
</xsl:function>
<xsl:template match="/">
<xsl:apply-templates select="chapter" />
<xsl:apply-templates select="appendix" />
</xsl:template>
<xsl:template match="chapter开发者_StackOverflow社区">
...
<xsl:apply-templates select="section" />
</xsl:template>
<xsl:template match="appendix">
...
<xsl:apply-templates select="section" />
</xsl:template>
<xsl:template match="section">
...
<xsl:apply-templates />
</xsl:template>
<xsl:template match="//chapter/section">
<xsl:if test="ex:isValidChapter(@name)">
<fo:block>
<xsl:number format="1."/>
<xsl:value-of select="@name" />
</fo:block>
<xsl:apply-templates />
</xsl:if>
</xsl:template>
...
</xsl:stylesheet>
The answer is simply to provide a count=
attribute to your <xsl:number>
instruction:
<xsl:number format="1." count="section[ex:isValidChapter(@name)]"/>
Thus in numbering the sections, only sections that are "valid" will be counted, so the numbering will be correct.
Note also that you need to modify your template that says:
<xsl:template match="/">
<xsl:apply-templates select="chapter" />
since <chapter>
is not a child of the root node. (It is a child of the document element, <book>
.) E.g.
<xsl:template match="/book">
<xsl:apply-templates select="chapter" />
Also, your function doesn't need a choose/when/otherwise to turn a boolean result into a boolean. It can be shortened to:
<xsl:function name="ex:isValidChapter" as="xs:boolean">
<xsl:param name="str-in" as="xs:string"/>
<xsl:sequence select="contains($validChapters, $str-in)"/>
</xsl:function>
精彩评论