2010-01-07 5 views
2

특정 xs:decimal이보고되어야하는 소수 자릿수가 형제 노드에서 유지되는 XML 문서가 있습니다. 저는 현재 format-number 함수를 통해 이것을 출력하는 간단한 방법을 찾기 위해 애 쓰고 있습니다.XPath 형식 - 변수를 기반으로하는 소수 자릿수가있는 숫자입니까?

나는 다른 기능을 가진 그림 문자열을 만들 수 있지만, 이것은 (적어도 imo) 상대적으로 직선적 인 일반적인 작업에 대해 그리 오래 참을 것 같습니다.

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

더 나은 방법이 있나요 : 이런 식으로 뭔가 내가 현재하고있어인가?

+1

미안하지만 'round ($ value * 100) div 100'을 사용하지 않는 이유는 무엇입니까? – iosadchii

+0

이렇게하면 후행 0이 추가되지 않기 때문입니다. 예 : 만약 myNode/DecimalPlaces = 4라면 100을 100.0000으로 출력하길 원합니다. – adhocgeek

답변

4

아주 좋은 질문입니다! 그 말은 보통, 나는 답을 모른다. 그러나 나는 다른 누군가도 이것이 나에게 고통이기 때문에 희망한다.

어쨌든, 나는 몇 가지 검색을했고, 나는 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) 
     ) 
    ) 
    ) 
    " 
/> 

물론이 공동 de는 원래보다 이 더 좋음이지만, XPath 1의 원래 질문을 해결하는 방법을 알고 누구보다 이보다 더 좋은 아이디어가 있다면, 나는 그것을 듣고 싶습니다. (점점 더 자주, 나는 세상이 모두 XML을 건너 뛰고 JSON 즉시 이동 한 것입니다 바랍니다)

+0

예. 나는 무거운 클라이언트 사이드 브라우저 XSLT 사용자입니다. 모의하지만 그것은 내가해야 할 일을 위해 아주 잘 작동합니다. 그러나 어떤 이유로 모든 브라우저가 여전히 XSLT 1.1/XPath 1에 갇혀 있습니다. 그래서 어떤 시점에서 그것을 빨아 들이고 일부 새끼 고양이를 고문하여 작업을 완료해야합니다. 그리고 이것과 같은 것들이 등장합니다. 고맙게도, 이런 종류의 헛소리를 보상하기위한 좋은 것들이 많이 있습니다. –

2
<!-- 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> 
+0

+1은 외형이 완벽합니다. – Filburt

+0

그래, 그렇게하는 또 다른 방법입니다. 나는 내가 그렇게 생각한다고 말하면서 크레딧을 얻을 수 없다는 것을 안다. 그러나 나는 그것을했다. OP는 더 나은 방법을 요구했기 때문에 그것을 게시하지 않았다. 나는 최대 정밀도가 미리 알려졌다는 표시가 없기 때문에이 점을 더 잘 고려하지 않았습니다. 개인적으로, 나는 어떤 이유로 'round-to-even()'을 사용할 수 없거나 최대 정밀도를 알고 있다면 분명히 이와 같은 솔루션을 사용할 것입니다.말했다 , 나는 매우 그냥이 간단한 일이 XPath에/XSLT에 너무 어렵다는 바나나되어있는 OP에 동의 –

+0

하나의 작은 최적화 CONCAT() ** ** 제거 할 수 있습니다와 '# 0을 넣어 . ' 상수로 변환 한 다음 하위 문자열 ** DecimalPlaces + 3 ** – Filburt

관련 문제