Reputation: 425401
I have a piece of XML
data which I need to transform into WML
.
It's something like this:
<root>
<category name="music"/>
<subcategory name="classic"/>
<subcategory name="rock"/>
<subcategory name="Techno"/>
<node type="music" subtype="classic" name="beethoven"/>
<node type="music" subtype="classic" name="chopin"/>
<record author="beethoven" name="moonlight sonata"/>
…
</root>
I cannot change the file structure.
Some Nokia
mobile browsers cannot load lots of <card>
's into memory.
So, depending on the mobile browser, the WML
page should be either a whole set of <card>
's, or some subset of <card>
's.
For instance, if I download a page with a normal browser, it should look like this:
<wml>
<card id="TOC">
<p><a href="#contents">Contents</a></p>
<p><a href="#az">A-Z</a></p>
</card>
<card id="contents">
<p><a href="#music">music</a></p>
<p><a href="#video">video</a></p>
<p><a href="#java">java</a></p>
</card>
<card id="az">
<p><a href="#beethoven">beethoven</a></p>
<p><a href="#chopin">chopin</a></p>
</card>
<card id="music">
<p><a href="#classic">classic</a></p>
<p><a href="#rock">rock</a></p>
<p><a href="#Techno">Techno</a></p>
</card>
<card id="classic">
<p><a href="#beethoven">beethoven</a></p>
<p><a href="#chopin">chopin</a></p>
</card>
…
</wml>
, so that the user can browse without extra round-trips to the server.
However, when I use Nokia
and visit the start page, the page should look like this:
http://example.com/
<wml>
<card id="TOC">
<p><a href="#contents">Contents</a></p>
<p><a href="#az">A-Z</a></p>
</card>
<card id="contents">
<p><a href="#music">music</a></p>
<p><a href="#video">video</a></p>
<p><a href="#java">java</a></p>
</card>
<card id="az">
<p><a href="/beethoven">beethoven</a></p>
<p><a href="/chopin">chopin</a></p>
</card>
<card id="music">
<p><a href="/classic">classic</a></p>
<p><a href="/rock">rock</a></p>
<p><a href="/Techno">Techno</a></p>
</card>
<card id="video">
<p><a href="/movies">Movies</a></p>
</card>
<card id="java">
<p><a href="/games">Games</a></p>
</card>
</wml>
, when I visit the href
, it should show the inner contents:
http://example.com/classic
<wml>
<card id="TOC">
<p><a href="#contents">Contents</a></p>
<p><a href="#az">A-Z</a></p>
</card>
<card id="contents">
<p><a href="/music">music</a></p>
<p><a href="/video">video</a></p>
<p><a href="/java">java</a></p>
</card>
<card id="az">
<p><a href="#beethoven">beethoven</a></p>
<p><a href="#chopin">chopin</a></p>
</card>
<card id="classic">
<p><a href="#beethoven">beethoven</a></p>
<p><a href="#chopin">chopin</a></p>
</card>
…
</wml>
Basically, the XSLT
should do the following things:
Accept some kind of a parameter of what is to be shown: the category, the subcategory etc.
Count the <card>
's that would be shown.
2
cards (we always show them)
10
cards.100
cards.300
cards.Nokia
cannot handle more than 120
cards, so we just stop on level 3
.
If XML
changes and level 3
requires 130
cards, we should stop on level 2
.
Don't show a <card>
if it is below certain level
Replace the #
(inner links) with /
(outer links) if the card is not to be shown.
Is it possible to do in a single XSL
file?
Upvotes: 0
Views: 262
Reputation: 14048
My understanding is that XSL is turing complete so the answer to pretty much any 'is it possible?' question is going to be yes. The answer to 'are you going to like it?', maybe not so much :-)
A simple way to do it and keep it modular would to use <xsl:param> to pass in the control parameters, and <xsl:choose> to select the format you want to display, and then branch/delegate to specific templates or functions for each format.
Where your formats have things in common you can DRY it up by delegating those parts to their own templates or functions, reusing them in the higher level templates for the main formats. Divide and conquer basically.
edit: to be more specific about what I mean by delegating, I mean explicitly calling templates and parameterising them, e.g.:
<xsl:call-template name="showcard">
<xsl:with-param name="kind" select="nokia"/>
</xsl:call-template>
With those templates in turn delegating to others, etc. You can also get a lot from value-of and apply-templates directing the flow to specific templates. Though your case is probably simpler, this may lead to more readable code.
Upvotes: 0
Reputation: 56572
I'd suggest creating variables which accumulatively count all the nodes of each "level" (type, subtype, title, …) and provide a parameter to your XSL indicating the maximum number of cards to generate. The XSL might look something like this:
<xsl:stylesheet …>
<xsl:param name="max-cards" select="999999"/>
<xsl:template match="/root">
<!-- "2" here for the type/TOC cards -->
<xsl:variable name="nSubs" select="2 + count(subcategory)"/>
<xsl:variable name="nNodes" select="$nSubs + count(node)"/>
<xsl:variable name="nRecs" select="$nNodes + count(record)"/>
<!-- generate types & TOC here -->
<xsl:if test="$nSubs < $max-cards">
<!-- generate subtypes here -->
</xsl:if>
<xsl:if test="$nNodes < $max-cards">
<!-- generate titles here -->
</xsl:if>
<xsl:if test="$nRecs < $max-cards">
<!-- generate everything else here -->
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Stylesheet parameters could be similarly used to restrict the generation of upper levels, but an example for that would be excessively long for SO. ^.^
Upvotes: 0
Reputation: 101595
I'm not sure what the question really is. As phrased, the answer is "yes, it is possible" - xsl:if
and xsl:choose
should be quite sufficient to handle all your conditions. You'll have to communicate restrictions (such as the fact that the result will go to a Nokia) to the stylesheet via parameters - see xsl:param
.
Upvotes: 1