You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用XSLT 1.0将价格字符串中的.00替换为€?

问题描述

需将XML中<prixmenu>29.00-90.00</prixmenu>转换为<prixmenu>29€-90€</prixmenu>,现有XSLT 1.0代码处理时出现以下问题:

  • 递归拆分模板输出2990,丢失分隔符和欧元符号
  • 使用translate函数得到29€-9€,因字符替换规则不匹配导致错误

输入XML

<?xml version="1.0" encoding="UTF-8"?>
<data>
    <etablissement not="15.0" etoile="2" >
        <nom>L&#039;Auberge Asterix</nom>
        <index>AUBERGE ASTERIX (L&#039;)</index>
        <id>0123456789</id>
        <regionindex>Paris</regionindex>
        <equipe>
            <chef>Ratatouille</chef>
        </equipe>
        <pictoPratique cave_remarquable="0"  coeur="0" ></pictoPratique>
        <coordonnees>
            <adresse>Random adress</adresse>
            <tel>01 23 45 67 89</tel>
            <fermetures>mam,maa,</fermetures>
            <pratique terrasse="0"
                voiturier="0"
                parcPrive="1"
                handicap="0"
                airConditione="0"
                piscine="0"
                tennis="0"
                chien="1"
                relaischat="0"
                delivery="0"
                clickAndCollect="0"
                itineraireGourmand="0"
                menu_kids="1"
                hebergement="0"
                ></pratique>
        </coordonnees>
        <texte>Lorem ipsum</texte>
        <prixrestau>
            <prixcarte>0</prixcarte>
            <prixmenu>29.00-90.00</prixmenu>
        </prixrestau>
    </etablissement>
</data>

现有XSLT代码

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes" />
  <xsl:strip-space elements="*" />
  
  <xsl:template match="data | node()[not(self::coordonnees)]">
    <xsl:copy>
      <xsl:apply-templates select="nom" />
      
      <xsl:choose>
        <xsl:when test="@etoile = 1">
          <etoile>1 étoile</etoile>
        </xsl:when>
        <xsl:when test="@etoile > 1">
          <etoile><xsl:value-of select="@etoile" /> étoiles</etoile>
        </xsl:when>
      </xsl:choose>
      
      <xsl:apply-templates select="index" />
      <xsl:apply-templates select="id" />
      <xsl:apply-templates
        select="@*[not(.='0')][name() != 'etoile'] | node()[not(self::index)][not(self::id)][not(self::prixrestau)][not(self::nom)][not(self::etoile)]" />
    </xsl:copy>
  </xsl:template>
  
  <xsl:template match="@*[name() != 'etoile']">
    <xsl:element name="{name()}">
      <xsl:value-of select="number(.)" />
    </xsl:element>
  </xsl:template>
  
  <xsl:template match="prixrestau/prixmenu" name="split">
    <xsl:param name="pText" select="."/>
    <xsl:if test="$pText">
      <xsl:value-of select="number(substring-before(concat($pText, '-'), '-'))"/>
      <xsl:call-template name="split">
        <xsl:with-param name="pText" select="substring-after($pText, '-')"/>
      </xsl:call-template>
    </xsl:if>
  </xsl:template>
  
  <xsl:template match="coordonnees">
    <xsl:copy>
      <xsl:apply-templates select="adresse" />
      <xsl:apply-templates select="tel" />
      <xsl:element name="prixrestau">
<xsl:value-of select="translate(../prixrestau/prixmenu,'.00.','€')"/>

        <xsl:apply-templates select="../prixrestau/prixcarte[not(.='0')]" />

        <xsl:element name="prixmenu">
          <xsl:apply-templates select="../prixrestau/prixmenu" />
        </xsl:element>
        
      </xsl:element>
      <xsl:apply-templates select="fermetures" />
      <xsl:apply-templates
        select="@*[not(.='0')] | node()[not(self::adresse)][not(self::tel)][not(self::fermetures)]" />
    </xsl:copy>
  </xsl:template>
  
</xsl:stylesheet>

期望输出

<?xml version="1.0"?>
<data>
  <etablissement>
    <nom>L'Auberge Asterix</nom>
    <etoile>2 étoiles</etoile>
    <index>AUBERGE ASTERIX (L')</index>
    <id>0123456789</id>
    <not>15</not>
    <regionindex>Paris</regionindex>
    <equipe>
      <chef>Ratatouille</chef>
    </equipe>
    <pictoPratique/>
    <coordonnees>
      <adresse>Random adress</adresse>
      <tel>01 23 45 67 89</tel>
      <prixrestau><prixmenu>29€-90€</prixmenu></prixrestau>
      <fermetures>mam,maa,</fermetures>
      <pratique>
        <parcPrive>1</parcPrive>
        <chien>1</chien>
        <menu_kids>1</menu_kids>
      </pratique>
    </coordonnees>
    <texte>Lorem ipsum</texte>
  </etablissement>
</data>

解决方案

方案1:XSLT 1.0 实现(无需FXSL)

替换原有prixrestau/prixmenu模板,通过递归拆分价格段并替换.00为€,保留分隔符:

<xsl:template match="prixrestau/prixmenu" name="formatPrice">
  <xsl:param name="text" select="."/>
  <xsl:choose>
    <!-- 处理带分隔符的价格范围 -->
    <xsl:when test="contains($text, '-')">
      <xsl:value-of select="concat(substring-before($text, '.00'), '€')"/>
      <xsl:text>-</xsl:text>
      <xsl:call-template name="formatPrice">
        <xsl:with-param name="text" select="substring-after($text, '-')"/>
      </xsl:call-template>
    </xsl:when>
    <!-- 处理单个价格 -->
    <xsl:otherwise>
      <xsl:value-of select="concat(substring-before($text, '.00'), '€')"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

同时删除coordonnees模板中多余的translate调用行:

<xsl:value-of select="translate(../prixrestau/prixmenu,'.00.','€')"/>

方案2:切换到XSLT 2.0(更简洁)

利用XSLT 2.0的正则替换函数replace,一步完成格式转换:

<xsl:template match="prixrestau/prixmenu">
  <xsl:copy>
    <xsl:value-of select="replace(., '(\d+)\.00', '$1€')"/>
  </xsl:copy>
</xsl:template>

此方法无需递归,代码更简洁易维护。


内容的提问来源于stack exchange,提问作者amsived

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 06:56:55