views:

80

answers:

2

xml:

<mode>1</mode>
<mode>2</mode>
<mode>3</mode>
<mode>4</mode>
<mode>5</mode>
<mode>6</mode>
<mode>7</mode>
<mode>8</mode>
<mode>9</mode>
<mode>10</mode>
<mode>11</mode>
<mode>12</mode>

i need to separate it on parts (for ex. on 4):

xslt:

<xsl:variable name="vNodes" select="mode"/>
<xsl:variable name="vNumParts" select="4"/>
<xsl:variable name="vNumCols" select="ceiling(count($vNodes) div $vNumParts)"/>
<xsl:for-each select="$vNodes[position() mod $vNumCols = 1]">
    <xsl:variable name="vCurPos" select="(position()-1)*$vNumCols +1"/>
    <ul>
        <xsl:for-each select="$vNodes[position() >= $vCurPos and not(position() > $vCurPos + $vNumCols -1)]">
            <li><xsl:value-of select="."/></li>
        </xsl:for-each>
    </ul>
</xsl:for-each>

this code is written by Dimitre Novatchev - great coder))

but for the number of nodes less then number of parts (for ex. i have 2 modes) this code does not work - it outputs nothing.

How it upgrade for that case (without choose construction)?

A: 

but for the number of nodes less then number of parts (for ex. i have 2 modes) this code does not work - it outputs nothing.

Actually, the code works correctly.

Whenever the number of parts is greater than the number of nodes, there is no solution to the problem: "Divide 2 nodes into 4 parts in equal number" -- the only solution is that each part contains 0 nodes.

Now you are solving a new, different problem and no wonder the solution to a different problem does not work for this new problem.

The way to go is to formulate the new problem correctly and to ask it. Then many people will be glad to answer.

Dimitre Novatchev
@Dimitre Novatchev, frankly, I was convinced that the logic of the issue is clear and understandable that we should get in the output. But you must agree with me that it is rather strange to ask about the code, which in one case displays all right, and the other simply does not output anything, although the input is. well, I agree that I am bad asked, not sufficiently clear. next time I will try harder.
Kalinin
@Kalinin: Do not expect any satisfactory solution unless you explain what it means to divide two things in four parts.
Dimitre Novatchev
@Dimitre Novatchev, you're right. this is my mistake. i apologize.
Kalinin
+1  A: 

Although the problem is incorrectly defined if the number of nodes is smaller than the number of parts, here is a transformation that I guess produces the output the OP most probably wants (Why didn't he just specify this behavior???):

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="node()|@*">
   <xsl:copy>
     <xsl:apply-templates select="node()|@*"/>
   </xsl:copy>
 </xsl:template>

 <xsl:template match="/t">
  <t>
    <xsl:variable name="vNodes" select="mode"/>
    <xsl:variable name="vNumParts" select="4"/>
    <xsl:variable name="vNumCols" select="ceiling(count($vNodes) div $vNumParts)"/>

    <xsl:variable name="vrealNum">
      <xsl:choose>
        <xsl:when test="$vNumCols >1">
         <xsl:value-of select="$vNumCols"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="count($vNodes)"/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>
    <xsl:for-each select="$vNodes[position() mod $vrealNum = 1]">
        <xsl:variable name="vCurPos" select="(position()-1)*$vrealNum +1"/>
        <ul>
            <xsl:for-each select="$vNodes[position() >= $vCurPos and not(position() > $vCurPos + $vrealNum -1)]">
                <li><xsl:value-of select="."/></li>
            </xsl:for-each>
        </ul>
    </xsl:for-each>
  </t>
 </xsl:template>
</xsl:stylesheet>

when this transformation is applied on the following XML document (he can't even provide a well-formed XML document!):

<t>
    <mode>1</mode>
    <mode>2</mode>
</t>

the output is what I guess the OP wanted...

<t>
    <ul>
        <li>1</li>
        <li>2</li>
    </ul>
</t>
Dimitre Novatchev