I’ve got a problem with some XSLT transformations.
In my XML data there are some Coordinate Elements like this:
XML:
[...]
<polygon some="attributes">
<coordinates>
<point>(8.234/9.435)</point>
<point>(2.456/5.678)</point>
[...]
</coordinates>
</polygon>
[...]
And so on.
The value of represents an x and a y coordinate (x/y).
Now I have to get from specific coordinate sets the biggest or the smallest value of x OR y.
We are using msxml in our c++ code so I can’t use XSLT 2.0 or XPath 2.0 for min() and max() functions.
The format (x/y) is static and I cant change it as well, because it’s an output of a program.
I tried to do it in XSLT like this:
XSLT:
<xsl:template name="getMinOf"> <!--this one is getting nodeset, min/max, x/y params-->
<xsl:for-each select="$nodeSet"> <!--in this case "//polygon/coordinates/point"-->
*<xsl:choose>
<xsl:when test="$MinOrMax = 'min' ">
<xsl:choose>
<xsl:when test="$XorY = 'x'">*
<xsl:sort select="substring-before(substring-after(.,'('),'/')" data-type="number" order="ascending"/> <!--Here is my problem-->
<xsl:if test="position() = 1">
<xsl:value-of select="." /><!-- return xMin -->
</xsl:if>
</xsl:when>
[...]
</xsl:template>
The select=”substring-before(substring-after(.,'(‘),’/’)” should get the part between ( and /, the x coordinate.
If i do a
<!--this one does return the x value.-->
<xsl:value-of select="substring-before(substring-after(.,'('),'/')"/>
So… I hope you can understand my problem and can help me. I don’t know how to get further.
Thanks.
Edit:
Forgot the desired output. It should be something like this:
<polygon>
<xMin>2.456</xMin>
<xMax>8.234</xMax>
<yMin>5.678</yMin>
<yMax>9.435</yMax>
</polygon>
Although not mentioned in the question, I am guessing your issue is that your are getting the message “Keyword xsl:sort may not be used here.”, which occurs because your xsl:sort is nested within an xsl:when when it should be directly under the xsl:for-each
Effectively you are trying to do conditional sorting, based on your parameter. One condition is whether to sort on either the x or y co-ordinate, and the other whether to sort ascending or descending.
For the ordering, you can define a variable, which will holding either ‘ascending’ or ‘descending’, and then order by that:
The next issue is how to do select either the ‘x’ or ‘y’ co-ordinate based on your parameter. One way could be to have a xsl:choose to choose between the sorting methods
However, there is a way to avoid this potential code duplication, and have a single xsl:for-each. Try this for the sort
This takes advantage of the fact that
($XorY = 'x')will evaluate to either 0 or 1 in the expression. To understand it more, it is effectively doing a concatenation of these two expressions:When $XorY = ‘x’ then 1 is returned, so the first substring (the x co-ordinate) returns a full string, but the second substring returns an empty string. When $XorY = ‘y’ the opposite is true and the second substring (the y co-ordinate) is returned.
Try this XSLT
When applied to your sample XML, the following is output