xslt: поиск значения, ближайшего к другому значению в списке - PullRequest
3 голосов
/ 01 февраля 2011

Приветствия, учитывая список чисел, возможно ли найти значение, наиболее близкое к данному значению, с помощью xslt?Например, если я ищу значение, близкое к 5 в списке [1,7], то 7 будет им.Аналогично для [4,9] это будет 4. Список может быть любой длины.

Спасибо.

Ответы [ 2 ]

2 голосов
/ 01 февраля 2011

Эта таблица стилей:

<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 голос
/ 01 февраля 2011

I. Решение 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...