开发者

count the number of elements in an XSL for-each loop?

I have been trying for the past day to figure out how to count the number of elements in an XSL for-each loop. I have tried doing it with javascript but can't seem to get开发者_JAVA技巧 it to work. I'm not sure if it's just a matter of not displaying the output correctly or if you can even do this with XSLT. Any help would be appreciated. This is a nasty bug that I was not prepared for.

<script type="text/javascript">
var colATotal=0;

function loopCounterA(){
  colATotal++;
}

function printA(){
   document.write(colATotal);
}
</script>

<xsl:for-each select='bookmarks/category'>
<xsl:for-each select='./bookmark'>

<script type="text/javascript">
loopCounterA(); 
printA();
</script>

</xsl:for-each>
</xsl:for-each>

From comments:

I figured showing all the code may be a waste of time. I have a div columnA and a div columnB, both of which are vertical columns. My boss wants all of the bookmarks to wrap, but i can't start the wrap in the middle of a category block. My intention is to keep track of 3 variables to do this: total bookmarks in columnA so far (A), total bookmarks in columnB so far (B), and the number of bookmarks in the next category block to be placed (C). if B + C is greater than A, I will place the block into columnA and I'll place it into columnB otherwise. Does this make more sense now? Thx so much.


This stylesheet (your algorithm):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="bookmarks">
        <html>
            <xsl:apply-templates select="category[1]"/>
        </html>
    </xsl:template>
    <xsl:template match="category">
        <xsl:param name="pColumnA" select="/.."/>
        <xsl:param name="pColumnB" select="/.."/>
        <xsl:variable name="vTest" select="count($pColumnB/bookmark|bookmark)
                                           > count($pColumnA/bookmark)"/>
        <xsl:variable name="vColumnA" select="$pColumnA|self::*[$vTest]"/>
        <xsl:variable name="vColumnB" select="$pColumnB|self::*[not($vTest)]"/>
        <xsl:variable name="vNext" select="following-sibling::category[1]"/>
        <xsl:apply-templates select="$vNext">
            <xsl:with-param name="pColumnA" select="$vColumnA"/>
            <xsl:with-param name="pColumnB" select="$vColumnB"/>
        </xsl:apply-templates>
        <xsl:if test="not($vNext)">
            <div id="ColumnA">
                <xsl:copy-of select="$vColumnA"/>
            </div>
            <div id="ColumnB">
                <xsl:copy-of select="$vColumnB"/>
            </div>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

With this input:

<bookmarks>
    <category id="a">
        <bookmark id="1"/>
        <bookmark id="2"/>
        <bookmark id="3"/>
    </category>
    <category id="b">
        <bookmark id="4"/>
        <bookmark id="5"/>
    </category>
    <category id="c">
        <bookmark id="6"/>
        <bookmark id="7"/>
        <bookmark id="8"/>
        <bookmark id="9"/>
        <bookmark id="10"/>
    </category>
    <category id="d">
        <bookmark id="11"/>
        <bookmark id="12"/>
        <bookmark id="13"/>
        <bookmark id="14"/>
        <bookmark id="15"/>
    </category>
</bookmarks>

Output:

<html>
    <div id="ColumnA">
        <category id="a">
            <bookmark id="1"></bookmark>
            <bookmark id="2"></bookmark>
            <bookmark id="3"></bookmark>
        </category>
        <category id="c">
            <bookmark id="6"></bookmark>
            <bookmark id="7"></bookmark>
            <bookmark id="8"></bookmark>
            <bookmark id="9"></bookmark>
            <bookmark id="10"></bookmark>
        </category>
    </div>
    <div id="ColumnB">
        <category id="b">
            <bookmark id="4"></bookmark>
            <bookmark id="5"></bookmark>
        </category>
        <category id="d">
            <bookmark id="11"></bookmark>
            <bookmark id="12"></bookmark>
            <bookmark id="13"></bookmark>
            <bookmark id="14"></bookmark>
            <bookmark id="15"></bookmark>
        </category>
    </div>
</html>


Use the count() XPath function on the predicate in the select attribute.


You can use the count() function and use it to simplify your JavaScript. No need to iterate over the XML to generate JavaScript that gets invoked n number of times to produce a count.

<script type="text/javascript">
var colATotal=<xsl:value-of select='count(bookmarks/category/bookmark)'>;

function printA(){
   document.write(colATotal);
}

printA();

</script>

If the goal of putting it into the JavaScript is just to turn it into HTML that has the count and you were just using JavaScript in order to create the HTML that you want(and couldn't figure out how to do in XSLT), try asking how to do it in XSLT.

It isn't as hard as you might imagine, it's just done differently than you may be used to. XSLT is a declarative programming style and you are approaching it as a procedural programmer.

You could just select the count of the elements and put it directly into your HTML output e.g.:

<b>The total count of bookmarks is:</b> <xsl:value-of select='count(bookmarks/category/bookmark)'>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜