Okay. I've reworked my original approach somewhat and am closer to a
satisfactory solution, but I'm still looking for a little deeper
understanding of a few concepts and, even better, a more complete
solution.
So, now, based on the same example XML provided below, I'm doing this:
<table>
<th>Header</th>
<xsl:apply-templates select="node[valid = 1 and position() <= 100]"
/>
</table>
<xsl:for-each select="node[valid = 1 and position() mod 100=1 and position()
>
100]">
<table cellpadding="0" cellspacing="0" border="0">
<xsl:apply-templates
select=".|following-sibling::node[valid = 1 and position() < 100]" />
</table>
</xsl:for-each>
<xsl:for-each select="node[not(valid = 1) and position() mod 100=1 and
position() >
100]">
<table cellpadding="0" cellspacing="0" border="0">
<xsl:apply-templates
select=".|following-sibling::node[not(valid = 1) and position() < 100]" />
</table>
</xsl:for-each>
<xsl:template match="node[valid=1]">
<tr>
<td class="valid">
<xsl:variable name="number">
<xsl:number
value="count(preceding-sibling::output)+1" level="any"
format="1" />
</xsl:variable>
<xsl:value-of select="$number" />.
<xsl:value-of select="data" />
</td>
</tr>
</xsl:template>
<xsl:template match="node[not(valid=1)]">
<tr>
<td class="invalid">
<xsl:variable name="number">
<xsl:number
value="count(preceding-sibling::output)+1" level="any"
format="1" />
</xsl:variable>
<xsl:value-of select="$number" />.
<xsl:value-of select="data" />
</td>
</tr>
</xsl:template>
The main difference here is that I'm doing selective template
application rather than sorting.
What I'm discovering, though, is that once all nodes that have a valid
node are output, my current method skips any nodes that are not valid
until the first complete set of 100 (I.e., where mod 100 = 1).
E.g., If I have 150 valid nodes and then 150 invalid nodes, this
stylesheet seems to output all 150 valid nodes, skips 50 invalid nodes
and then prints the final 100 invalid nodes.
I would've thought I could've overcome this by including something along
the lines of:
<xsl:for-each select="node[not(valid = 1) and position() =
count(node[valid = 1]) + 1]">
<table cellpadding="0" cellspacing="0" border="0">
<xsl:apply-templates
select=".|following-sibling::node[not(valid = 1)
and not(position() mod 100 = 1)]" />
</table>
</xsl:for-each>
As I understand the grouping, I would've thought this would start with
the node whose position was immediately after the last valid node and
then iterate until it hit a node with mod 100 = 1, but it doesn't seem
to be working.
Is my interpretation of how this grouping strategy works correct?
What can I do to output these interim nodes successfully (and most
appropriately)?
Thanks!
-tfo
I have some XML that looks like this:
<data>
<node>
<data>data</data>
<valid>1</valid>
</node>
<node>
<data>data</data>
</node>
</data>
There can be any number and sequence of nodes. Some nodes are flagged
with a validity node.
I'm trying to transform it to HTML using XSL. Here are the conditions:
1. Group it by 100.
2. Sort it by whether or not the nodes have a "valid" node (descending
from valid to non-valid, which is just a binary existence check).
3. The output needs to be numbered sequentially.
4. The output needs to be formatted differently based on whether a
"valid" node is encountered.
5. The first chunk of the output needs to include a header.
Basically, I'm breaking it up into 100-row HTML tables.
Here's my current approach:
<table>
<th>Header</th>
<xsl:apply-templates select="node[position() <= 100]">
<xsl:sort select="valid" />
</xsl:apply-templates>
</table>
<xsl:for-each select="node[position() mod 100=1 and position() >
100]">
<table cellpadding="0" cellspacing="0" border="0">
<xsl:apply-templates
select=".|following-sibling::node[position()<100]">
<xsl:sort select="valid" />
</xsl:apply-templates>
</table>
</xsl:for-each>
<xsl:template match="node[valid=1]">
<tr>
<td class="valid">
<xsl:variable name="number">
<xsl:number
value="count(preceding-sibling::*)+1" level="any"
format="1" />
</xsl:variable>
<xsl:value-of select="$number" />.
<xsl:value-of select="data" />
</td>
</tr>
</xsl:template>
<xsl:template match="node[not(valid=1)]">
<tr>
<td class="invalid">
<xsl:variable name="number">
<xsl:number
value="count(preceding-sibling::*)+1" level="any"
format="1" />
</xsl:variable>
<xsl:value-of select="$number" />.
<xsl:value-of select="data" />
</td>
</tr>
</xsl:template>
Unfortunately, the result of this transformation neither sorts the
output, nor numbers the output sequentially. The grouping works, but I
was under the impression that the sort would apply to the nodes before
their positions were considered. What I understand less is why the sort
does not seem actually to order the nodes correctly in the output.
Any help is much appreciated.
Thanks!
-tfo