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 gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Min and Max values of a node

Status
Not open for further replies.

Sarky78

Programmer
Oct 19, 2000
878
GB
Hi,

Me again!!

I am loooping over an element within my xml document using xslt, and need to be able to find the min and the max values of a node within the document.

this is the basic structure of the document
Code:
<Root>
  <Table>
    <ypos>6</ypos>
    <xpos>100</xpos>
  </Table>
  <Table>
    <ypos>7</ypos>
    <xpos>101</xpos>
  </Table>
</Root>

Now I am looping over this information like:

Code:
<xsl:for-each select="//Table">
  <xsl:sort select="xpos" data-type="number"/>

  <xsl:if test="position()=1">
    <xsl:value-of select="ypos" /><br />
    <xsl:value-of select="ypos[position()=last()]" /><br />
    <xsl:value-of select="ypos[position()]" /><br />
  </xsl:if>
</xsl:for-each>

<!--  position element on the page here using css-->

Now I have tried using an if statement with the test position()=last() to test for the last element in my document and therefore give me the smallest value, and I have used position()=1 to test for the first element, but when trying to use the variables I am setting within these if statements later the parser says that they aren't available, so i tried the above solution. this seems to be looking at the same node within the document, and not the last element within the whole document.

It is at this point that i run out of tallent

Does anyone know how i can find the smallest ypos and the largest ypos which will then allow me to position an element on the page once the loop has finsihed?

TIA

Tony
 
Min ypos:
Code:
<xsl:value-of select="min(Root/Table/ypos)"/>
Max ypos:
Code:
<xsl:value-of select="max(Root/Table/ypos)"/>

Jon

"I don't regret this, but I both rue and lament it.
 
Jon,

Thanks for the response. I've seen the min and max functions on the w3schools site, and tried them using ColdFusion and ASP.Net and they both throw the same error
"'min()' is an unknown XSLT function"

We are using .net 1.1 and CF 7.01, this is the code that i now have:

Code:
<xsl:for-each select="//Table">
  <xsl:sort select="xpos" data-type="number"/>
    <xsl:if test="position()=1">
      <xsl:call-template name="stage">
	<xsl:with-param name="yposMin" select="min(ypos)" />
	<xsl:with-param name="yposMax" select="max(ypos)" />
      </xsl:call-template>
    </xsl:if>

Is this something that is within XSLT 2 and not 1?

TIA

Tony
 
If it is the min or max you want to find on ypos, I wonder why xpos is being sorted to begin with. Suppose ypos is what you want to determine the min/max, to get the (xpos, ypos) corresponding to the min and max of ypos, you can do something like this.
[tt]
<xsl:for-each select="//ypos">
<xsl:sort select="." data-type="number" order="ascending"/> <!-- ascending is default -->
<xsl:if test="position() = 1"> <!-- hence min ypos-->
<xsl:value-of select="." /><br /> <!-- ypos min -->
<xsl:value-of select="../xpos" /><br /> <!-- corresponding xpos -->
</xsl:if>
<xsl:if test="position() = last()"> <!-- hence max ypos -->
<xsl:value-of select="." /><br /> <!-- ypos max -->
<xsl:value-of select="../xpos" /><br /> <!-- corresponding xpos -->
</xsl:if>
</xsl:for-each>
[/tt]
 
tsuji,

The data is sorted on the xpos so that we can loop over the rows within the document, initially and this will in turn sort the info as we want it.

What i need to be able to do is to get the min and max values for the ypos so that i can then perform some calculations on the values. If I needed to output the information then your solution would work. I have tried setting variables within these if statements before and the value of the position=1 is not "rememberd" later in the document when i come to use the variables.

Tony
 
If you want the (x,ymax) and (x,ymin) pairs for general usage over the xsl, you can make it to parameters of global scope, so that you can reference to them globally.
[tt]
<xsl:param name="ymax">
<xsl:for-each select="//ypos">
<xsl:sort select="." data-type="number" order="descending"/>
<xsl:if test="position() = 1">
<xsl:value-of select="." />
</xsl:if>
</xsl:for-each>
</xsl:param>
<xsl:param name="xpos_ymax">
<xsl:for-each select="//ypos">
<xsl:sort select="." data-type="number" order="descending"/>
<xsl:if test="position() = 1">
<xsl:value-of select="../xpos" />
</xsl:if>
</xsl:for-each>
</xsl:param>
<xsl:param name="ymin">
<xsl:for-each select="//ypos">
<xsl:sort select="." data-type="number" order="ascending"/>
<xsl:if test="position() = 1">
<xsl:value-of select="." />
</xsl:if>
</xsl:for-each>
</xsl:param>
<xsl:param name="xpos_ymin">
<xsl:for-each select="//ypos">
<xsl:sort select="." data-type="number" order="ascending"/>
<xsl:if test="position() = 1">
<xsl:value-of select="../xpos" />
</xsl:if>
</xsl:for-each>
</xsl:param>
[/tt]
So anywhere in the xsl, you can reference them by $xpos_ymin, $ymin and $xpos_ymax, $ymax. Or I miss something.
 

yeah i have seen an implementation like that, but decided against it as out xml document has in some cases more then 700 Table elements, meaning that we would be looping 1400 times to get the values of the ypos min and max and then looping 700 more times to output the information to the screen.

I can't believe how hard this is just to get two values out of a document, and then use these in a calculation later in the document.
 
Can't remember where I got this code from:

<xsl:variable name="maxVal">
<xsl:call-template name="max">
<xsl:with-param name="list" select="Person/PersonCode"/>
</xsl:call-template>
</xsl:variable>
<xsl:text>The max value is:</xsl:text>
<xsl:value-of select="$maxVal"/>
<xsl:text> The next value is:</xsl:text>
<xsl:value-of select="$maxVal + 1"/>


<xsl:template name="max">
<xsl:param name="list"/>
<xsl:choose>
<xsl:when test="$list">
<xsl:variable name="first" select="$list[1]"/>
<xsl:variable name="max-of-rest">
<xsl:call-template name="max">
<xsl:with-param name="list" select="$list[position()!=1]"/>
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test="$first > $max-of-rest">
<xsl:value-of select="$first"/>
</xsl:when>
<xsl:eek:therwise>
<xsl:value-of select="$max-of-rest"/>
</xsl:eek:therwise>
</xsl:choose>
</xsl:when>
<xsl:eek:therwise>0</xsl:eek:therwise>
</xsl:choose>
</xsl:template>
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top