Pergunta

Eu tenho um documento XML onde o número de decimal coloca um xs:decimal particular deve ser relatado na é realizada em um nó irmão. Atualmente estou lutando para encontrar uma maneira simples para a saída dessa via a função format-number.

Eu posso construir uma seqüência de imagem com algumas outras funções, mas isso parece terrivelmente prolixo para o que deveria ser (pelo menos imo) uma tarefa relativamente simples e comum.

por exemplo. o que eu estou fazendo atualmente é algo como isto:

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

Existe uma maneira melhor?

Foi útil?

Solução

Muito boa pergunta! Isso normalmente significa, eu não sei a resposta, mas eu espero que alguém o faça, pois isso é uma dor para mim também.

De qualquer forma, eu fiz alguma pesquisa e eu acho que a função round-half-to-even pode fazer o truque ( http://www.xqueryfunctions.com/xq/fn_round-half-to-even.html )

Seu código seria:

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

Agora fora por um pouco de tangente: Para as pessoas que estão usando XSLT 1.1 ou inferior e XPath 1, você poderia usar o seguinte:

<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)
        )
      )
    )
  "
/>

É claro, esse código é pior do que o original, mas se alguém sabe como resolver a questão original para XPath 1 e tem uma ideia melhor do que isso, eu adoraria ouvir isso. (Mais e mais frequentemente, eu desejo que o mundo teria XML totalmente ignorada e mudou-se imediatamente para JSON)

Outras dicas

<!-- 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))
  )
" />

Você pode abstrair-lo em um template:

<!-- 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" />

Você também pode fazer um modelo chamado e usar o nó de contexto XSLT quando chamá-lo. Depende um pouco do seu documento de entrada e necessidades, se isso é viável para você.

<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>
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top