xslt 2.0 getting two points of a list for interpolation

R

RolfK

Dear ALL,

does anybody have a solution for this:
I have a set of points (you can imagine a poly line) decribed this
way.

<?xml version="1.0" encoding="UTF-8"?>
<Line>
<P X="10" Y="1.0"/>
<P X="20" Y="2.1"/>
<P X="30" Y="2.2"/>
<P X="40" Y="4.3"/>
<P X="50" Y="4.4"/>
<P X="60" Y="3.5"/>
</Line>

What I want is to create a function which returns the Y value based on
an X value.
Easy, in case the X value exists. If not, I have to search the 2
nearest points and next calculate Y.
I can assume that the X value is in the range of Xmin and Xmax of the
point data set.

What is the best code (XSLT2.0) to find the two nearest points for a
given X ?
(I have the feeling that a for-each-group may do, but this may be
wrong)

Any help is welcome

Rolf
 
M

Martin Honnen

RolfK said:
<Line>
<P X="10" Y="1.0"/>
<P X="20" Y="2.1"/>
<P X="30" Y="2.2"/>
<P X="40" Y="4.3"/>
<P X="50" Y="4.4"/>
<P X="60" Y="3.5"/>
</Line>

What I want is to create a function which returns the Y value based on
an X value.
Easy, in case the X value exists. If not, I have to search the 2
nearest points and next calculate Y.
I can assume that the X value is in the range of Xmin and Xmax of the
point data set.

Are the P elements ordered by the X attribute value, as in your sample
above?
 
R

RolfK

Hello Martin,

yes, we should assume that. If not I would sort the nodeset before.

Rolf
 
M

Martin Honnen

RolfK said:
yes, we should assume that.

If the P elements are sorted on @X then it should be easy, look for the
last P where @X is less than $X and for the first P where @X is greater
than $X.

The following stylesheet:

<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:mf="http://example.com/2008/mf"
exclude-result-prefixes="xsd mf">

<xsl:eek:utput method="xml" indent="yes"/>

<xsl:function name="mf:find-points" as="element()+">
<xsl:param name="X" as="xsd:integer"/>
<xsl:param name="points" as="element()+"/>
<xsl:sequence
select="$points[xsd:integer(@X) lt $X][last()],
$points[xsd:integer(@X) gt $X][1]"/>
</xsl:function>

<xsl:template match="/">
<result>
<xsl:variable name="root" select="/"/>
<xsl:for-each select="(10, 12, 25, 33, 40, 58)">
<result X="{.}">
<xsl:choose>
<xsl:when test="$root/Line/P[xsd:integer(@X) eq current()]">
<xsl:copy-of select="$root/Line/P[xsd:integer(@X) eq
current()]"/>
</xsl:when>
<xsl:eek:therwise>
<xsl:copy-of select="mf:find-points(., $root/Line/P)"/>
</xsl:eek:therwise>
</xsl:choose>
</result>
</xsl:for-each>
</result>
</xsl:template>

</xsl:stylesheet>

when run against your XML input sample outputs

<result>
<result X="10">
<P X="10" Y="1.0"/>
</result>
<result X="12">
<P X="10" Y="1.0"/>
<P X="20" Y="2.1"/>
</result>
<result X="25">
<P X="20" Y="2.1"/>
<P X="30" Y="2.2"/>
</result>
<result X="33">
<P X="30" Y="2.2"/>
<P X="40" Y="4.3"/>
</result>
<result X="40">
<P X="40" Y="4.3"/>
</result>
<result X="58">
<P X="50" Y="4.4"/>
<P X="60" Y="3.5"/>
</result>
</result>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,016
Latest member
TatianaCha

Latest Threads

Top