求助:使用XSLT将XML响应转为指定JSON数组并支持随机排序
解决XSLT转换XML为指定JSON数组并随机排序的问题
核心需求实现
要把XML中的响应文本转换成[{"Response":"响应文本"},...]格式的JSON数组,同时支持随机排序(哪怕10条数据),以下是针对不同XSLT版本的可行方案:
假设源XML结构
先假设你的源XML是类似这样的结构(如果实际结构不同,只需调整XSLT中的节点路径即可):
<Responses> <Response>这是第一条响应内容</Response> <Response>这是第二条响应内容</Response> <Response>这是第三条响应内容</Response> <Response>这是第四条响应内容</Response> <Response>这是第五条响应内容</Response> </Responses>
XSLT 3.0 实现(推荐,支持原生随机排序)
XSLT 3.0提供了random-number-generator()函数,可以直接生成无重复的随机排列序列,确保排序完全随机:
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text" encoding="UTF-8"/> <xsl:template match="/"> <!-- 开启JSON数组 --> <xsl:text>[</xsl:text> <!-- 对所有Response节点按随机序列排序 --> <xsl:for-each select="Responses/Response"> <xsl:sort select="random-number-generator(current-dateTime())?permute(1 to count(../Response))[position()]" order="ascending"/> <!-- 非第一个元素前加逗号分隔 --> <xsl:if test="position() > 1">,</xsl:if> <!-- 输出指定JSON结构,转义双引号避免格式错误 --> <xsl:text>{"Response":"</xsl:text> <xsl:value-of select="replace(., '"', '\"')"/> <xsl:text>"}</xsl:text> </xsl:for-each> <!-- 闭合JSON数组 --> <xsl:text>]</xsl:text> </xsl:template> </xsl:stylesheet>
关键说明:
random-number-generator(current-dateTime()):用当前时间作为随机种子,确保每次运行排序结果不同。permute(1 to count(../Response)):生成和响应节点数量一致的随机排列序列,每个节点对应唯一的排序值,不会出现排序冲突。replace(., '"', '\"'):转义文本中的双引号,防止破坏JSON结构;如果有换行、反斜杠等其他特殊字符,可添加额外的replace处理,比如replace(., '\n', '\\n')。
XSLT 1.0 实现(依赖扩展函数)
XSLT 1.0原生没有随机函数,需要依赖EXSLT的math:random()扩展(主流处理器如Saxon、Xalan均支持):
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:math="http://exslt.org/math" extension-element-prefixes="math"> <xsl:output method="text" encoding="UTF-8"/> <xsl:template match="Responses"> <xsl:text>[</xsl:text> <!-- 按随机数排序响应节点 --> <xsl:apply-templates select="Response"> <xsl:sort select="math:random()" order="ascending"/> </xsl:apply-templates> <xsl:text>]</xsl:text> </xsl:template> <xsl:template match="Response"> <xsl:if test="position() > 1">,</xsl:if> <xsl:text>{"Response":"</xsl:text> <xsl:value-of select="translate(., '"', '\"')"/> <xsl:text>"}</xsl:text> </xsl:template> </xsl:stylesheet>
关键说明:
math:random()会给每个节点生成0-1之间的随机数,以此作为排序依据,对于10条数据来说,出现重复随机数的概率极低,可满足需求。translate(., '"', '\"'):XSLT 1.0中用translate实现双引号转义。
适配调整
如果你的源XML中响应文本的节点路径不同,比如响应文本在<Answer><Content>...</Content></Answer>中,只需把XSLT中的Responses/Response替换成//Answer/Content即可。
内容的提问来源于stack exchange,提问作者Buddi
相关产品推荐
相关产品推荐

