Search code examples
xmlperformancexsltxslt-2.0processing-efficiency

Super-efficient way to report on whether or not there are fiction books costing more than $10


My XML document consists of a series of Book elements of various genres (fiction, non-fiction, etc.)

I want to create an XSLT template that outputs true if:

  1. There are no fiction Books.

  2. There are fiction Books and each costs less than or equal to $10.00

I want the template to output false if:

  1. There are fiction Books that cost greater than $10.00

My template below does the job, but I am hoping you can provide a more efficient solution. My template takes a lot of steps to solve such a simple problem. I suspect that my template would have poor performance with a large set of data. Can you provide a super-efficient solution to the problem?

Here's my template:

<xsl:template match="Books">
    <xsl:variable name="fiction-books" select="Book[Genre eq 'Fiction']" />
    <xsl:variable name="no-fiction-books-that-cost-more-than-10-dollars" select="not(exists(Book[Genre eq 'Fiction'][number(Cost) gt 10.00]))" />
    <xsl:variable name="no-fiction-books" select="not(exists($fiction-books))" />

    <xsl:value-of select="$no-fiction-books or $no-fiction-books-that-cost-more-than-10-dollars" />
</xsl:template>

Here's a sample input (the XSLT should output false with this input):

<Books>
    <Book>
        <Title>ABC</Title>
        <Genre>Fiction</Genre>
        <Cost>10.00</Cost>
    </Book>
    <Book>
        <Title>DEF</Title>
        <Genre>Fiction</Genre>
        <Cost>20.00</Cost>
    </Book>
</Books>

Solution

  • I want the template to output false if:

    1. There are fiction Books that cost greater than $10.00

    How about:

    <xsl:template match="/Books">
        <xsl:value-of select="not(Book[Genre='Fiction']/Cost >10)" />
    </xsl:template>
    

    Note that the output is not XML.