XPath تنسيق رقم مع عدد من الأماكن العشرية بناء على متغير؟

StackOverflow https://stackoverflow.com/questions/2021720

  •  19-09-2019
  •  | 
  •  

سؤال

لدي مستند 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'))"
/>

هل هناك طريقة أفضل؟

هل كانت مفيدة؟

المحلول

سؤال جيد جدا! هذا يعني عادة، لا أعرف الجواب ولكن آمل أن يفعل شخص آخر لأن هذا هو ألم بالنسبة لي أيضا.

على أي حال، فعلت بعض البحث وأعتقد round-half-to-even وظيفة قد تفعل الخدعة (http://www.xqueryfults.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)

نصائح أخرى

<!-- 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>
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top