Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>If your processor can do <a href="http://www.exslt.org/exsl/index.html" rel="nofollow">the <code>exslt:node-set</code> function</a> or an equivalent such as <a href="http://msdn.microsoft.com/en-us/library/hz88kef0%28v=vs.71%29.aspx" rel="nofollow">that provided by msxml</a> then you could attack this procedurally, using a tail-recursive template. Ugly, I know, and completely against what we usually recommend for XSLT, but in this case I think the only way to do this efficiently is to pass information from one row to the next. Assuming that the <em>first</em> row of the table will always have an <code>entry</code> for every column, then how about something like this:</p> <pre><code>&lt;xsl:template match="tbody"&gt; &lt;w:tbl&gt; &lt;xsl:apply-templates select="row[1]"&gt; &lt;xsl:with-param name="rowSpec"&gt; &lt;!-- build the row info structure assuming that the first row has the right number of entry elements. Nothing spans into the first row, so they all get @span=0 --&gt; &lt;xsl:for-each select="row[1]/entry"&gt; &lt;r span="0" /&gt; &lt;/xsl:for-each&gt; &lt;/xsl:with-param&gt; &lt;/xsl:apply-templates&gt; &lt;/w:tbl&gt; &lt;/xsl:template&gt; &lt;xsl:template match="row"&gt; &lt;xsl:param name="rowSpec" /&gt; &lt;xsl:variable name="theRow" select="." /&gt; &lt;w:tr&gt; &lt;!-- build up the output for this row --&gt; &lt;xsl:for-each select="exsl:node-set($rowSpec)/r"&gt; &lt;w:tc&gt; &lt;xsl:choose&gt; &lt;xsl:when test="@span = 0"&gt; &lt;!-- this row has an entry for the column --&gt; &lt;xsl:apply-templates select="$theRow/entry[ count(current()/preceding-sibling::r[@span = 0]) + 1]" /&gt; &lt;/xsl:when&gt; &lt;xsl:otherwise&gt; &lt;!-- this column spans from the previous row --&gt; &lt;w:tcPr&gt; &lt;w:vMerge/&gt; &lt;/w:tcPr&gt; &lt;w:p/&gt; &lt;/xsl:otherwise&gt; &lt;/xsl:choose&gt; &lt;/w:tc&gt; &lt;/xsl:for-each&gt; &lt;/w:tr&gt; &lt;!-- process the next row with recalculated spans --&gt; &lt;xsl:apply-templates select="following-sibling::row[1]"&gt; &lt;xsl:with-param name="rowSpec"&gt; &lt;xsl:for-each select="exsl:node-set($rowSpec)/r"&gt; &lt;xsl:choose&gt; &lt;xsl:when test="@span = 0"&gt; &lt;!-- we had an entry element for this column, use its @morerows as the next span, or 0 if it doesn't have one --&gt; &lt;xsl:choose&gt; &lt;xsl:when test="$theRow/entry[ count(current()/preceding-sibling::r[@span = 0]) + 1]/@morerows"&gt; &lt;r span="{$theRow/entry[ count(current()/preceding-sibling::r[@span = 0]) + 1]/@morerows}" /&gt; &lt;/xsl:when&gt; &lt;xsl:otherwise&gt; &lt;r span="0" /&gt; &lt;/xsl:otherwise&gt; &lt;/xsl:choose&gt; &lt;/xsl:when&gt; &lt;xsl:otherwise&gt; &lt;!-- we didn't have an entry for this column, it was a span from the previous row - subtract 1 from the span when we pass on to the next row --&gt; &lt;r span="{@span - 1}" /&gt; &lt;/xsl:otherwise&gt; &lt;/xsl:choose&gt; &lt;/xsl:for-each&gt; &lt;/xsl:with-param&gt; &lt;/xsl:apply-templates&gt; &lt;/xsl:template&gt; &lt;xsl:template match="entry"&gt; &lt;w:p&gt; &lt;w:r&gt; &lt;w:t&gt;&lt;xsl:value-of select="." /&gt;&lt;/w:t&gt; &lt;/w:r&gt; &lt;/w:p&gt; &lt;/xsl:template&gt; </code></pre> <p>(Wow, that ended up much more complex than I expected when I started it, but I've tested it out and it seems to work correctly). The idea here is that we build a structure that encodes the number of rows that each column still needs to span over at the point where that row is processed. So for the first row we'll have</p> <pre><code>&lt;r span="0"/&gt; &lt;r span="0"/&gt; &lt;r span="0"/&gt; &lt;r span="0"/&gt; </code></pre> <p>then for the second it'll be</p> <pre><code>&lt;r span="2"/&gt; &lt;r span="1"/&gt; &lt;r span="0"/&gt; &lt;r span="0"/&gt; </code></pre> <p>the third</p> <pre><code>&lt;r span="1"/&gt; &lt;r span="0"/&gt; &lt;r span="0"/&gt; &lt;r span="0"/&gt; </code></pre> <p>etc. For each row we then iterate over <em>this structure</em> rather than over the <code>entry</code> elements themselves.</p> <hr> <p>Edit: now you've changed the question so you need to account for the possibility of column spans as well as row spans it gets much much messier. Since we're committed to using a node-set function, I would think about a two-step approach as hinted at by LarsH, where you first expand out the column spanning entries into real <code>entry</code> elements (with some attribute to identify them as such) and then process the expanded version of the XML in place of the original.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload