Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Count function in XSL

Status
Not open for further replies.

TomBarrand

Programmer
Aug 9, 2000
162
0
0
GB
Hi,

I have an XML document similar to the structure below. I need to know how many <FORECASTDETAIL> elements there are in the document. I used COUNT(/FORECAST/ITEM/MONTH/FORECASTDETAIL), but this only returns the number of <FORECASTDETAIL> elements within one <MONTH> element and not the total number of <FORECASTDETAIL> elements in the document.

Any ideas?

Thanks

<FORECAST>
<ITEM>
<MONTH>
<FORECASTDETAIL></FORECASTDETAIL>
</MONTH>
<MONTH>
<FORECASTDETAIL></FORECASTDETAIL>
</MONTH>
<MONTH>
<FORECASTDETAIL></FORECASTDETAIL>
</MONTH>
</ITEM>
</FORECAST>
 
The XPath you have specified will return ALL the FORECASTDETAIL elements that are in ANY /FORECAST/ITEM/MONTH. So I'm guessing the XML shown is not the same structure as your actual XML file. Post your actual XML and XSL.

You could use count(//FORECASTDETAIL) but this is very inefficient.
 
The XML is detailed below. I have got round it by using count(//FORECASTDETAIL).

I have a similar issue with position()

I have some code like: concat('NEWQUANTITY_',position()). This is within a <xsl:for-each select="FORECASTDETAIL">. The position gives me the values with FORECASTDETAIL within the MONTH, but I need the position in the whole doc. E.g. If I have 5 FORECASTDETAIL in a MONTH then position returns, 1 -5, but it also returns 1-5 for the next month. I need it to go 6-10, 11-15, etc until it gets to the last FORECASTDETAIL in the document.

Hope that makes sense.

Thanks for your help

<?xml version="1.0"?>
<FORECAST xmlns="">
<DATAFOUND>TRUE</DATAFOUND>
<ITEM>
<SHIPTO>5011899</SHIPTO>
<ITEMNO>19010</ITEMNO>
<ITEMDESCRIPTION>AAAAAAA</ITEMDESCRIPTION>
<CustProdCode>Cust Prod Code</CustProdCode>
<ITEMSTATUS>S</ITEMSTATUS>
<PalletBuild>Pallets</PalletBuild>
<ProductionTag>SCA</ProductionTag>
<WebImagePath> <MONTH>
<FORECASTYEAR>2005</FORECASTYEAR>
<FORECASTMONTH>2</FORECASTMONTH>
<FORECASTDETAIL>
<FORECASTWEEK>A</FORECASTWEEK>
<UPDATEABLE>FALSE</UPDATEABLE>
<FORECASTQUANTITY>0</FORECASTQUANTITY>
<NewQuantity>0</NewQuantity>
<ForecastDate>2005-10-01</ForecastDate>
</FORECASTDETAIL>
<FORECASTDETAIL>
<FORECASTWEEK>B</FORECASTWEEK>
<UPDATEABLE>TRUE</UPDATEABLE>
<FORECASTQUANTITY>0</FORECASTQUANTITY>
<NewQuantity>0</NewQuantity>
<ForecastDate>2005-10-01</ForecastDate>
</FORECASTDETAIL>
<FORECASTDETAIL>
<FORECASTWEEK>C</FORECASTWEEK>
<UPDATEABLE>TRUE</UPDATEABLE>
<FORECASTQUANTITY>0</FORECASTQUANTITY>
<NewQuantity>0</NewQuantity>
<ForecastDate>2005-10-01</ForecastDate>
</FORECASTDETAIL>
<FORECASTDETAIL>
<FORECASTWEEK>D</FORECASTWEEK>
<UPDATEABLE>TRUE</UPDATEABLE>
<FORECASTQUANTITY>0</FORECASTQUANTITY>
<NewQuantity>0</NewQuantity>
<ForecastDate>2005-10-01</ForecastDate>
</FORECASTDETAIL>
<FORECASTDETAIL>
<FORECASTWEEK>E</FORECASTWEEK>
<UPDATEABLE>TRUE</UPDATEABLE>
<FORECASTQUANTITY>0</FORECASTQUANTITY>
<NewQuantity>0</NewQuantity>
<ForecastDate>2005-10-01</ForecastDate>
</FORECASTDETAIL>
</MONTH>
<MONTH>
<FORECASTYEAR>2005</FORECASTYEAR>
<FORECASTMONTH>3</FORECASTMONTH>
<FORECASTDETAIL>
<FORECASTWEEK>A</FORECASTWEEK>
<UPDATEABLE>TRUE</UPDATEABLE>
<FORECASTQUANTITY>0</FORECASTQUANTITY>
<NewQuantity>0</NewQuantity>
<ForecastDate>2005-10-01</ForecastDate>
</FORECASTDETAIL>
<FORECASTDETAIL>
<FORECASTWEEK>B</FORECASTWEEK>
<UPDATEABLE>TRUE</UPDATEABLE>
<FORECASTQUANTITY>120</FORECASTQUANTITY>
<NewQuantity>0</NewQuantity>
<ForecastDate>2005-03-08</ForecastDate>
</FORECASTDETAIL>
<FORECASTDETAIL>
<FORECASTWEEK>C</FORECASTWEEK>
<UPDATEABLE>TRUE</UPDATEABLE>
<FORECASTQUANTITY>60</FORECASTQUANTITY>
<NewQuantity>0</NewQuantity>
<ForecastDate>2005-03-15</ForecastDate>
</FORECASTDETAIL>
<FORECASTDETAIL>
<FORECASTWEEK>D</FORECASTWEEK>
<UPDATEABLE>TRUE</UPDATEABLE>
<FORECASTQUANTITY>0</FORECASTQUANTITY>
<NewQuantity>0</NewQuantity>
<ForecastDate>2005-10-01</ForecastDate>
</FORECASTDETAIL>
<FORECASTDETAIL>
<FORECASTWEEK>E</FORECASTWEEK>
<UPDATEABLE>TRUE</UPDATEABLE>
<FORECASTQUANTITY>0</FORECASTQUANTITY>
<NewQuantity>0</NewQuantity>
<ForecastDate>2005-10-01</ForecastDate>
</FORECASTDETAIL>
</MONTH>
<MONTH>
<FORECASTYEAR>2005</FORECASTYEAR>
<FORECASTMONTH>4</FORECASTMONTH>
<FORECASTDETAIL>
<FORECASTWEEK>A</FORECASTWEEK>
<UPDATEABLE>TRUE</UPDATEABLE>
<FORECASTQUANTITY>0</FORECASTQUANTITY>
<NewQuantity>0</NewQuantity>
<ForecastDate>2005-10-01</ForecastDate>
</FORECASTDETAIL>
<FORECASTDETAIL>
<FORECASTWEEK>B</FORECASTWEEK>
<UPDATEABLE>TRUE</UPDATEABLE>
<FORECASTQUANTITY>160</FORECASTQUANTITY>
<NewQuantity>0</NewQuantity>
<ForecastDate>2005-04-05</ForecastDate>
</FORECASTDETAIL>
<FORECASTDETAIL>
<FORECASTWEEK>C</FORECASTWEEK>
<UPDATEABLE>TRUE</UPDATEABLE>
<FORECASTQUANTITY>0</FORECASTQUANTITY>
<NewQuantity>0</NewQuantity>
<ForecastDate>2005-10-01</ForecastDate>
</FORECASTDETAIL>
<FORECASTDETAIL>
<FORECASTWEEK>D</FORECASTWEEK>
<UPDATEABLE>TRUE</UPDATEABLE>
<FORECASTQUANTITY>0</FORECASTQUANTITY>
<NewQuantity>0</NewQuantity>
<ForecastDate>2005-10-01</ForecastDate>
</FORECASTDETAIL>
<FORECASTDETAIL>
<FORECASTWEEK>E</FORECASTWEEK>
<UPDATEABLE>TRUE</UPDATEABLE>
<FORECASTQUANTITY>0</FORECASTQUANTITY>
<NewQuantity>0</NewQuantity>
<ForecastDate>2005-10-01</ForecastDate>
</FORECASTDETAIL>
</MONTH>
</ITEM>
</FORECAST>
 
count(/FORECAST/ITEM/MONTH/FORECASTDETAIL) returns 15 for me. You must be using it in a different context.

Regarding the position thing, you could do it using a variable, but there's probably a neater solution. Post your XSL.
 
<xsl:template name="forecastDetails" match="FORECAST/ITEM/FORECASTDETAIL">
<form action="wsrp_rewrite?wsrp-urlType=blockingAction&amp;verb=callFourthService/wsrp_rewrite" method="post" name="FormName">
<table border="0" cellpadding="2" cellspacing="1" class="matrix" width="790" align="center">
<tr>
<td class="conf">Details:</td>
<th class="weeks">Week 1</th>
<th class="weeks">Week 2</th>
<th class="weeks">Week 3</th>
<th class="weeks">Week 4</th>
<th class="weeks">Week 5</th>
</tr>
<!-- Normalize space removes the space in the ITEMNO data that is coming back from the web service -->
<input type="hidden" name="ITEMNO" value="{normalize-space(//ITEMNO)}"/>
<!--<input type="hidden" name="SHIPTO" value="{//SHIPTO}"/>-->
<input type="hidden" name="SHIPTO" value=""/>
<xsl:for-each select="/FORECAST/ITEM/MONTH">
<xsl:variable name="formelemn1" select="concat(FORECASTMONTH, '_')"/>
<tr>
<td width="130" class="matrixBold">
<xsl:call-template name="displayMonthNames">
<xsl:with-param name="monthNo" select="FORECASTMONTH"/>
</xsl:call-template> - <xsl:call-template name="displayYear"><xsl:with-param name="yearNo" select="FORECASTYEAR"/></xsl:call-template></td>

<xsl:for-each select="FORECASTDETAIL">
<xsl:variable name="formelemn2" select="concat($formelemn1, FORECASTYEAR)"/>
<td class="matrixCell" width="132">
<xsl:choose>
<xsl:when test="UPDATEABLE = 'TRUE'">
<!-- If the NewQuantity XML element equals zero then the quantity that is displayed should be the FORECASTQUANTITY -->
<!-- Otherwise the NewQuantity should be displayed -->
<xsl:variable name="newQuantity">
<xsl:choose>
<xsl:when test="NewQuantity='0'">
<xsl:value-of select="FORECASTQUANTITY"/>
</xsl:when>
<xsl:eek:therwise>
<xsl:value-of select="NewQuantity"/>
</xsl:eek:therwise>
</xsl:choose>
</xsl:variable>
<input class="formElems" type="text" size="10" name="{concat('NEWQUANTITY_',position())}" value="{$newQuantity}"/>&#160;
<input type="hidden" name="{concat('FORECASTQUANTITY_',position())}" value="{FORECASTQUANTITY}"/>

<input type="hidden" name="{concat('FORECASTDATE_',position())}" value="{ForecastDate}"/>
<input type="hidden" name="{concat('UPDATEABLE_',position())}" value="{UPDATEABLE}"/>
<!-- <input type="hidden" name="{concat('TEST_','MONTH_',../FORECASTMONTH,'_YEAR_',../FORECASTYEAR,'_',position())}" value="{UPDATEABLE}"/>
<input type="hidden" name="{concat('TOM_',FORECASTDETAIL[position()>1]}" value="{UPDATEABLE}"/>-->
<!--items/item[position()>1]-->
</xsl:when>
<xsl:when test="UPDATEABLE != 'TRUE'">
<!-- If the NewQuantity XML element equals zero then the quantity that is displayed should be the FORECASTQUANTITY -->
<!-- Otherwise the NewQuantity should be displayed -->
<xsl:variable name="newQuantity">
<xsl:choose>
<xsl:when test="NewQuantity='0'">
<xsl:value-of select="FORECASTQUANTITY"/>
</xsl:when>
<xsl:eek:therwise>
<xsl:value-of select="NewQuantity"/>
</xsl:eek:therwise>
</xsl:choose>
</xsl:variable>
<xsl:value-of select="$newQuantity"/>&#160;
</xsl:when>
<xsl:eek:therwise>-</xsl:eek:therwise>
</xsl:choose>
</td>
</xsl:for-each>
</tr>
</xsl:for-each>
<tr>
<td colspan="3">&#160;
</td>
<td class="matrixcell" colspan="3" align="right">&#160;
<br/>

<!-- Hidden field to hold the total number of input boxes -->
<!--<input type="hidden" value="{count(/FORECAST/ITEM/FORECASTDETAIL)}" name="counter"/>-->
<!--<input type="hidden" value="{count(/FORECAST/ITEM/MONTH/FORECASTDETAIL)}" name="counter"/>-->
<!-- See how many FORECASTDETAIL elements there are in the XML document -->
<input type="hidden" value="{count(//FORECASTDETAIL)}" name="counter"/>
<input type="submit" name="submit" value="Confirm Values to William Grant"/>
<br/>
<br/>
</td>
</tr>
</table>
</form>
</xsl:template>
 
Any ideas anyone? This is proving to be a tricky one!
 
there isn't a FORECASTDETAIL within the context /FORECAST/ITEM/MONTH.

You have two for-each loops inside each other, and the first one is superceeding the second's context.

Think again about how you should be accessing FORCASTDETAIL.

Cheers

Matt

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top