RE: [xsl] min & max of numeric sub-strings

Subject: RE: [xsl] min & max of numeric sub-strings
From: Johan von Boisman <johan.von.boisman@xxxxxxxxxxxx>
Date: Mon, 4 Nov 2002 15:41:49 +0100
>I am trying to find the minimum and maximum values for the X and Y values
>within the start|end elements of all the <Line>s in the XML file (ie. minX,
>minY, maxX, maxY).  Does anyone have a simple/elegant solution or any
>suggestions?

>Thankyou
>Adrian

<Parcels>
  <Parcel name="801" area="554.065">
    <CoordGeom>
      <Line>
        <Start>33505.95684580 31533.46501647</Start>
        <End>33516.39685788 31545.58962565</End>
      </Line>
      <Line>
        <Start>33516.39685788 31545.58962565</Start>
        <End>33542.33349683 31523.25663165</End>
      </Line>
      ...
    </CoordGeom>
  </Parcel>
  <Parcel name="802" area="529.463">
    ...
  </Parcel>
  ...
</Parcels>


Try this program: (requires MSXML though, because of the msxsl:node-set
function)

<?xml version="1.0"?>
<t:transform version="1.0"
   xmlns:t="http://www.w3.org/1999/XSL/Transform";
   xmlns:msxsl="urn:schemas-microsoft-com:xslt">

 <t:output encoding="UTF-8" method="text" />

 <t:template match="/">
  <t:variable name="res">
  <t:call-template name="findMax">
   <t:with-param name="lines" select="Parcels/Parcel/CoordGeom/Line" />
   <t:with-param name="minX" select="100000000" />
   <t:with-param name="maxX" select="-100000000" />
   <t:with-param name="minY" select="100000000" />
   <t:with-param name="maxY" select="-100000000" />
  </t:call-template>
  </t:variable>
  MinX = <t:value-of select="msxsl:node-set($res)/minX" />
  MaxX = <t:value-of select="msxsl:node-set($res)/maxX" />
  MinY = <t:value-of select="msxsl:node-set($res)/minY" />
  MaxY = <t:value-of select="msxsl:node-set($res)/maxY" />
 </t:template>

 <t:template name="findMax">
  <t:param name="lines" />
  <t:param name="minX" />
  <t:param name="maxX" />
  <t:param name="minY" />
  <t:param name="maxY" />
  <t:choose>
   <t:when test="count($lines) = 0">
    <minX><t:value-of select="$minX" /></minX>
    <maxX><t:value-of select="$maxX" /></maxX>
    <minY><t:value-of select="$minY" /></minY>
    <maxY><t:value-of select="$maxY" /></maxY>
   </t:when>
   <t:otherwise>

    <t:variable name="car" select="msxsl:node-set($lines)[1]" />
    <t:variable name="cdr" select="msxsl:node-set($lines)[position() != 1]"
/>

    <t:variable name="X1" select="substring-before($car/Start, ' ')" />
    <t:variable name="Y1" select="substring-after($car/Start, ' ')" />

    <t:variable name="X2" select="substring-before($car/End, ' ')" />
    <t:variable name="Y2" select="substring-after($car/End, ' ')" />

    <t:variable name="localMinX">
     <t:call-template name="min">
      <t:with-param name="t1" select="$X1" />
      <t:with-param name="t2" select="$X2" />
     </t:call-template>
    </t:variable>

    <t:variable name="localMaxX">
     <t:call-template name="max">
      <t:with-param name="t1" select="$X1" />
      <t:with-param name="t2" select="$X2" />
     </t:call-template>
    </t:variable>

    <t:variable name="newMinX">
     <t:call-template name="min">
      <t:with-param name="t1" select="$minX" />
      <t:with-param name="t2" select="$localMinX" />
     </t:call-template>
    </t:variable>

    <t:variable name="newMaxX">
     <t:call-template name="max">
      <t:with-param name="t1" select="$maxX" />
      <t:with-param name="t2" select="$localMaxX" />
     </t:call-template>
    </t:variable>

    <t:variable name="localMinY">
     <t:call-template name="min">
      <t:with-param name="t1" select="$Y1" />
      <t:with-param name="t2" select="$Y2" />
     </t:call-template>
    </t:variable>

    <t:variable name="localMaxY">
     <t:call-template name="max">
      <t:with-param name="t1" select="$Y1" />
      <t:with-param name="t2" select="$Y2" />
     </t:call-template>
    </t:variable>

    <t:variable name="newMinY">
     <t:call-template name="min">
      <t:with-param name="t1" select="$minY" />
      <t:with-param name="t2" select="$localMinY" />
     </t:call-template>
    </t:variable>

    <t:variable name="newMaxY">
     <t:call-template name="max">
      <t:with-param name="t1" select="$maxY" />
      <t:with-param name="t2" select="$localMaxY" />
     </t:call-template>
    </t:variable>

    <t:variable name="cdrResult">
     <t:call-template name="findMax">
      <t:with-param name="lines" select="$cdr" />
      <t:with-param name="minX" select="$newMinX" />
      <t:with-param name="maxX" select="$newMaxX" />
      <t:with-param name="minY" select="$newMinY" /> 
      <t:with-param name="maxY" select="$newMaxY" />
     </t:call-template>
    </t:variable>

    <minX><t:value-of select="msxsl:node-set($cdrResult)/minX" /></minX>
    <maxX><t:value-of select="msxsl:node-set($cdrResult)/maxX" /></maxX>
    <minY><t:value-of select="msxsl:node-set($cdrResult)/minY" /></minY>
    <maxY><t:value-of select="msxsl:node-set($cdrResult)/maxY" /></maxY>
   </t:otherwise>
  </t:choose>
 </t:template>

 <t:template name="min">
  <t:param name="t1" />
  <t:param name="t2" />
  <t:choose>
   <t:when test="$t1 &lt; $t2">
    <t:value-of select="$t1" />
   </t:when>
   <t:otherwise>
    <t:value-of select="$t2" />
   </t:otherwise>
  </t:choose>
 </t:template>

 <t:template name="max">
  <t:param name="t1" />
  <t:param name="t2" />
  <t:choose>
   <t:when test="$t1 &gt; $t2">
    <t:value-of select="$t1" />
   </t:when>
   <t:otherwise>
    <t:value-of select="$t2" />
   </t:otherwise>
  </t:choose>
 </t:template>

</t:transform>

 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread