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

使用XSLT 2.0转XML到JSON时,如何为指定元素设置值类型?

问题描述

现有一套可正常将XML转换为JSON的XSLT,但无法控制JSON的数值类型。需求:当XML元素名为id且非空时,将其转换为JSON字符串类型。

尝试过以下模板但未生效:

<xsl:template match="id">
    <xsl:choose>
        <xsl:when test="id">
            <xsl:text/>"<xsl:value-of select="json:encode-string(.)"/>"<xsl:text/>
        </xsl:when>
    </xsl:choose>
</xsl:template>

现有XSLT代码片段:

<xsl:template match="json:name" mode="json">
    <xsl:text/>"<xsl:value-of select="json:encode-string(.)"/>" :<xsl:text/>
</xsl:template>

<xsl:template match="json:value" mode="json">
    <xsl:choose>
        <xsl:when test="node() and not(text())">
            <xsl:apply-templates mode="json"/>
        </xsl:when>
        <xsl:when test="text()">
            <xsl:choose>
                <xsl:when test="normalize-space(.) ne . or not((string(.) castable as xs:integer and not(starts-with(string(.),'+') or starts-with(string(.),'-')) and not(starts-with(string(.),'0') and not(. = '0'))) or (string(.) castable as xs:decimal and not(starts-with(string(.),'+')) and not(starts-with(.,'-.')) and not(starts-with(.,'.')) and not(starts-with(.,'-0') and not(starts-with(.,'-0.'))) and not(ends-with(.,'.')) and not(starts-with(.,'0') and not(starts-with(.,'0.'))))) and not(. = 'false') and not(. = 'true') and not(. = 'null')">
                    <xsl:text/>"<xsl:value-of select="json:encode-string(.)"/>"<xsl:text/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:text/><xsl:value-of select="."/><xsl:text/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:when>
        <xsl:otherwise>
            <xsl:text>null</xsl:text>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

使用的转换器为xsltjson项目的xml-to-json.xsl,示例XML:

<?xml version="1.0" encoding="UTF-8"?>
<ns0:TestMe xmlns:ns0="urn:hero:wakanda:Cle:Something">
  <root>
    <id>123</id>
    <field2>345</field2>
    <fee>
       <totalFee>123</totalFee>
   </fee>
   </root>
</ns0:TestMe>

疑问:如何按键值对遍历元素,根据元素名称添加值的条件逻辑?

解决方案

问题原因

之前的模板无效,是因为xsltjson的转换流程是先将原XML转换为json:name(对应键)和json:value(对应值)的中间结构,直接匹配原XML的id元素不会被执行,必须在处理json:value时,关联对应的json:name来做判断。

修改后的XSLT代码

调整json:value模板,在处理文本节点的分支中,优先判断当前值对应的键是否为id且非空,强制转换为字符串;其余情况保留原有逻辑:

<xsl:template match="json:name" mode="json">
    <xsl:text/>"<xsl:value-of select="json:encode-string(.)"/>" :<xsl:text/>
</xsl:template>

<xsl:template match="json:value" mode="json">
    <xsl:choose>
        <xsl:when test="node() and not(text())">
            <xsl:apply-templates mode="json"/>
        </xsl:when>
        <xsl:when test="text()">
            <xsl:choose>
                <!-- 优先处理id元素:判断对应的json:name是否为id,且当前值非空 -->
                <xsl:when test="../json:name = 'id' and normalize-space(.) != ''">
                    <xsl:text/>"<xsl:value-of select="json:encode-string(.)"/>"<xsl:text/>
                </xsl:when>
                <!-- 原有字符串判断逻辑 -->
                <xsl:when test="normalize-space(.) ne . or not((string(.) castable as xs:integer and not(starts-with(string(.),'+') or starts-with(string(.),'-')) and not(starts-with(string(.),'0') and not(. = '0'))) or (string(.) castable as xs:decimal and not(starts-with(string(.),'+')) and not(starts-with(.,'-.')) and not(starts-with(.,'.')) and not(starts-with(.,'-0') and not(starts-with(.,'-0.'))) and not(ends-with(.,'.')) and not(starts-with(.,'0') and not(starts-with(.,'0.'))))) and not(. = 'false') and not(. = 'true') and not(. = 'null')">
                    <xsl:text/>"<xsl:value-of select="json:encode-string(.)"/>"<xsl:text/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:text/><xsl:value-of select="."/><xsl:text/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:when>
        <xsl:otherwise>
            <xsl:text>null</xsl:text>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

效果说明

转换示例XML后,id的值会变成字符串类型的"123",而field2、totalFee仍保持数值类型345、123,符合需求。

遍历键值对的逻辑说明

通过../json:name可以获取当前json:value对应的键名,以此为依据添加条件判断。如果需要扩展其他元素的特殊处理,只需在json:value的文本判断分支中,新增类似的<xsl:when test="../json:name = '你的元素名'">逻辑即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 18:40:42