Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
779 views
in Technique[技术] by (71.8m points)

xslt - Rendering a node sequence as M x N table

@Oded: Sorry to have been poor in my exposition... My input document has a fragment like this:

<recordset name="resId" >
<record n="0">example 1</record>
<record n="1">example 2</record>
<record n="2">example 1</record>
....
<record n="N">example 1</record>
</recordset>

containing an arbitrarily long node sequence. The attribute "n" reports the order of the node in the sequence. I need to arrange as output that sequence in a M (rows) x N (columns) table and I have some trouble doing that. I cannot call a template

<xsl:template match="recordset">
   <table>
      <xsl:apply-templates select="record"/>
   </table>
</xsl:template>

with something like:

<xsl:template match="record">
<xsl:if test="@n mod 3 = 0">
    <tr>
</xsl:if>
........
<td><xsl:value-of select"something"></td>

because code is invalid (and I should repeat it at the end of the template in some way) and I must put some (maybe too much) trust in the presence of the numbered attribute. Someone has a hint? Thanks!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You must ensure that nesting is never broken. Things you want nested in the output must be nested in the XSLT.

<xsl:variable name="perRow" select="3" />

<xsl:template match="recordset">
  <table>
    <xsl:apply-templates 
      mode   = "tr"
      select = "record[position() mod $perRow = 1]"
    />
  </table>
</xsl:template>

<xsl:template match="record" mode="tr">
  <tr>
    <xsl:variable name="td" select="
      . | following-sibling::record[position() &lt; $perRow]
    " />
    <xsl:apply-templates mode="td" select="$td" />
    <!-- fill up the last row -->
    <xsl:if test="count($td) &lt; $perRow">
      <xsl:call-template name="filler">
        <xsl:with-param name="rest" select="$perRow - count($td)" />
      </xsl:call-template>
    </xsl:if>
  </tr>
</xsl:template>

<xsl:template match="record" mode="td">
  <td>
    <xsl:value-of select="." />
  </td>
</xsl:template>

<xsl:template name="filler">
  <xsl:param name="rest" select="0" />
  <xsl:if test="$rest">
    <td />
    <xsl:call-template name="filler">
      <xsl:with-param name="rest" select="$rest - 1" />
    </xsl:call-template>
  </xsl:if>
</xsl:template>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...