xslt:查找最接近列表中另一个值的值

时间:2011-01-31 23:18:40

标签: xslt

问候,给定一个数字列表,是否可以使用xslt找到最接近给定值的值?例如,如果我在列表[1,7]中寻找最接近5的值,那么就是7。同样地,对于[4,9],它将是4.列表可以是任何长度。

感谢。

2 个答案:

答案 0 :(得分:2)

此样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:param name="pValue" select="5"/>
    <xsl:template match="/">
        <xsl:for-each select="list/num">
            <xsl:sort select="(. - $pValue) * not(0 > . - $pValue )
                              - (. - $pValue) * (0 > . - $pValue)"/>
            <xsl:if test="position() = 1">
                <xsl:value-of select="."/>
            </xsl:if>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

使用此输入:

<list>
    <num>4</num>
    <num>9</num>
</list>

输出:

4

这个输入:

<list>
    <num>1</num>
    <num>7</num>
</list>

输出:

7

编辑:XSLT 2.0解决方案:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:param name="pValue" select="5"/>
    <xsl:template match="/">
        <xsl:variable name="vSequence"
                      select="/list/num/abs(. - $pValue)"/>
        <xsl:variable name="vMinimum"
                      select="min($vSequence)"/>
        <xsl:variable name="vPosition"
                      select="index-of($vSequence,$vMinimum)[1]"/>
        <xsl:value-of select="/list/num[$vPosition]"/>
    </xsl:template>
</xsl:stylesheet>

它表明它可能是一行XPath 2.0表达式:

/list/num[
   index-of(
      /list/num/abs(. - $pValue),
      min(/list/num/abs(. - $pValue))
   )[1]
]

答案 1 :(得分:1)

<强>予。 XSLT 1.0解决方案:

因为@Alejandro比我快,我现在不得不设计另一个解决方案:)

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common" xmlns:my="my:my">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <my:num>5.6</my:num>

 <xsl:param name="pValue" select="document('')/*/my:num"/>

 <xsl:variable name="vList" select="/*/*"/>

 <xsl:template match="/">
   <xsl:variable name="vrtfSorted">
     <xsl:for-each select="$vList | $pValue">
      <xsl:sort select="." data-type="number"/>
      <xsl:copy-of select="."/>
     </xsl:for-each>
   </xsl:variable>

   <xsl:variable name="vSorted" select="ext:node-set($vrtfSorted)/*"/>

   <xsl:variable name="vVal1" select=
    "$vSorted[.=$pValue]/preceding-sibling::*[1]"/>

   <xsl:variable name="vVal2" select=
    "$vSorted[.=$pValue]/following-sibling::*[1]"/>

   <xsl:value-of select=
    "($pValue - $vVal1 > $vVal2 - $pValue) * $vVal2
     +
     (not($pValue - $vVal1 > $vVal2 - $pValue)) * $vVal1
    "/>
 </xsl:template>
</xsl:stylesheet>

应用于以下XML文档(包含值列表):

<nums>
  <num>01</num>
  <num>02</num>
  <num>03</num>
  <num>04</num>
  <num>05</num>
  <num>06</num>
  <num>07</num>
  <num>08</num>
  <num>09</num>
  <num>10</num>
</nums>

产生了想要的正确结果

6

<强> II。 XSLT 2.0解决方案:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:param name="pNumber" as="xs:double" select="5.3"/>
 <xsl:param name="pList" as="xs:double+"
  select="3,2,5,7,8,6,4,9,1"/>

 <xsl:template match="/">
  <xsl:variable name="vSorted" as="xs:double+">
   <xsl:perform-sort select="$pList">
    <xsl:sort select="abs(. - $pNumber)"/>
   </xsl:perform-sort>
  </xsl:variable>
  <xsl:sequence select="$vSorted[1]"/>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于任何XML文档(未使用)时,会生成所需的正确结果:

5