Формат XPath-число с количеством десятичных знаков на основе переменной? - PullRequest
2 голосов
/ 07 января 2010

У меня есть XML-документ, в котором количество десятичных разрядов, о которых следует сообщить конкретный xs:decimal, хранится в узле-родственнике.В настоящее время я изо всех сил пытаюсь найти простой способ вывести это через функцию format-number.

Я могу построить строку изображения с некоторыми другими функциями, но это кажется ужасно скучным для того, что должно быть (вхотя бы imo) относительно простая и распространенная задача.

например, то, что я сейчас делаю, выглядит примерно так:

<xsl:value-of
 select="format-number(myNode/DecimalValue,
         concat('#0.', 
                string-join(for $i in 1 to myNode/DecimalPlaces return '0'))"
/>

Есть ли лучший способ?

Ответы [ 2 ]

4 голосов
/ 07 января 2010

Очень хороший вопрос! Это обычно означает, что я не знаю ответа, но я надеюсь, что кто-то еще знает, потому что это тоже для меня боль.

Во всяком случае, я провел поиск и думаю, что функция round-half-to-even может помочь (http://www.xqueryfunctions.com/xq/fn_round-half-to-even.html)

)

Ваш код станет:

<xsl:value-of 
  select="
    round-half-to-even(
      myNode/DecimalValue
    , myNode/DecimalPlaces
    )
  "
/>

Теперь немного по касательной: Для людей, которые используют XSLT 1.1 или ниже и XPath 1, вы можете использовать это:

<xsl:value-of 
  select="
    concat(
      substring-before(DecimalValue, '.')
    , '.'
    , substring(substring-after(DecimalValue, '.'), 1, DecimalPlaces -1)
    , round(
        concat(
          substring(substring-after(DecimalValue, '.'), DecimalPlaces, 1)
        ,   '.'
        ,   substring(substring-after(DecimalValue, '.'), DecimalPlaces+1)
        )
      )
    )
  "
/>

Конечно, этот код хуже , чем оригинал, но если кто-нибудь знает, как решить исходный вопрос для XPath 1, и у него есть идея получше, чем эта, я хотел бы услышать это. (Мне все чаще хотелось бы, чтобы мир вообще пропустил XML и сразу перешел на JSON)

2 голосов
/ 07 января 2010
<!-- use a generous amount of zeros in a top-level variable -->
<xsl:variable name="zeros" select="'000000000000000000000000000000000'" />

<!-- …time passes… -->
<xsl:value-of select="
  format-number(
     myNode/DecimalValue,
     concat('#0.', substring($zeros, 1, myNode/DecimalPlaces))
  )
" />

Вы можете абстрагировать его в шаблон:

<!-- template mode is merely to prevent collisions with other templates -->
<xsl:template match="myNode" mode="FormatValue">
  <xsl:value-of select="
    format-number(
      DecimalValue, 
      concat('#0.', substring($zeros, 1, DecimalPlaces))
    )
  " />
</xsl:template>

<!-- call like this -->
<xsl:apply-templates select="myNode" mode="FormatValue" />

Вы также можете создать именованный шаблон и использовать узел контекста XSLT при его вызове. Немного зависит от вашего входного документа и необходимости, если это возможно для вас.

<xsl:template name="FormatValue">
  <!-- same as above -->
</xsl:template>

<!-- call like this -->
<xsl:for-each select="myNode">
  <xsl:call-template name="FormatValue" />
</xsl:for-each>
...