xml转json的xslt脚本 v2.6
程序员文章站
2022-04-19 14:05:18
在v2.5版本基础上增加了对于嵌套数组输出的支持,但同时也增加了20%左右的执行耗时;两个版本均可以分别作为最终版本使用,因为在数据交换的应用需求场景,采取嵌套数组的情形几乎不会存在。当元素同时符合以下各项条件,子元素作为嵌套数组输出:1、正被输出为数组中的一项;2、不存在待输出属性;3、不存在文本节点;4、所有子元素与本元素同名;5、子元素应当按数组方式输出。脚本如下:
在v2.5版本基础上增加了对于嵌套数组输出的支持,但同时也增加了20%左右的执行耗时;两个版本均可以分别作为最终版本使用,因为在数据交换的应用需求场景,采取嵌套数组的情形几乎不会存在。
当元素同时符合以下各项条件,子元素作为嵌套数组输出:
1、正被输出为数组中的一项;
2、不存在待输出属性;
3、不存在文本节点;
4、所有子元素与本元素同名;
5、子元素应当按数组方式输出。
脚本如下:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="utf-8"/>
<xsl:template match="*">
<xsl:param name="indents"/><xsl:param name="inArray"/>
<xsl:choose>
<xsl:when test="$inArray = 1 and not(@*[not(starts-with(name(), 'json..')) and not(starts-with(name(), 'json:'))]) and not(text()) and not(*[name()!=name(..)][1]) and (*[1]/@json..Array or @*[name()='json:Array'] or *[2])">
<xsl:text>[</xsl:text>
<xsl:for-each select="*">
<xsl:if test="position() > 1">,</xsl:if>
<xsl:value-of select="concat('
', $indents, '	')"/>
<xsl:apply-templates select="."><xsl:with-param name="indents" select="concat($indents, '	')"/><xsl:with-param name="inArray" select="1"/></xsl:apply-templates>
</xsl:for-each>
<xsl:value-of select="concat('
', $indents)"/><xsl:text>]</xsl:text>
</xsl:when>
<xsl:when test="* or @*[not(starts-with(name(), 'json..')) and not(starts-with(name(), 'json:'))]">
<xsl:text>{</xsl:text>
<xsl:for-each select="@*[not(starts-with(name(), 'json..')) and not(starts-with(name(), 'json:'))]">
<xsl:if test="position() > 1">,</xsl:if>
<xsl:value-of select="concat('
', $indents, '	')"/>"@<xsl:value-of select="name()"/><xsl:text>":"</xsl:text>
<xsl:call-template name="output-string"><xsl:with-param name="string" select="."/></xsl:call-template>
<xsl:text>"</xsl:text>
<xsl:if test="position() = last()"><xsl:if test="../node()">,</xsl:if></xsl:if>
</xsl:for-each>
<xsl:for-each select="text()">
<xsl:if test="position() = 1">
<xsl:value-of select="concat('
', $indents, '	')"/>
<xsl:text>"#text":</xsl:text>
<xsl:if test="last() > 1">[</xsl:if>
</xsl:if>
<xsl:if test="position() > 1">,</xsl:if>
<xsl:if test="last() > 1">
<xsl:value-of select="concat('
', $indents, '		')"/>
</xsl:if>
<xsl:text>"</xsl:text>
<xsl:call-template name="output-string"><xsl:with-param name="string" select="."/></xsl:call-template>
<xsl:text>"</xsl:text>
<xsl:if test="position() = last()">
<xsl:if test="last() > 1"><xsl:value-of select="concat('
', $indents, '	')"/>]</xsl:if>
<xsl:if test="../*">,</xsl:if>
</xsl:if>
</xsl:for-each>
<xsl:for-each select="*">
<xsl:variable name="eleName" select="name()"/>
<xsl:choose>
<xsl:when test="preceding-sibling::*[name()=$eleName]" />
<xsl:otherwise>
<xsl:if test="position() > 1" >,</xsl:if>
<xsl:value-of select="concat('
', $indents, '	')"/>"<xsl:value-of select="name()"/><xsl:text>":</xsl:text>
<xsl:choose>
<xsl:when test="@json..Array or @*[name()='json:Array'] or following-sibling::*[name()=$eleName]">
<xsl:text>[</xsl:text>
<xsl:value-of select="concat('
', $indents, '		')"/>
<xsl:apply-templates select="."><xsl:with-param name="indents" select="concat($indents, '		')"/><xsl:with-param name="inArray" select="1"/></xsl:apply-templates>
<xsl:for-each select="following-sibling::*[name()=$eleName]">
<xsl:text>,</xsl:text>
<xsl:value-of select="concat('
', $indents, '		')"/>
<xsl:apply-templates select="."><xsl:with-param name="indents" select="concat($indents, '		')"/><xsl:with-param name="inArray" select="1"/></xsl:apply-templates>
</xsl:for-each>
<xsl:value-of select="concat('
', $indents, '	')"/>
<xsl:text>]</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="."><xsl:with-param name="indents" select="concat($indents, '	')"/></xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
<xsl:value-of select="concat('
', $indents)"/><xsl:text>}</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="@json..Type or @*[name()='json:Type']">
<xsl:choose>
<xsl:when test="text()"><xsl:value-of select="text()"/></xsl:when>
<xsl:otherwise>null</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="text()">
<xsl:text>"</xsl:text>
<xsl:call-template name="output-string"><xsl:with-param name="string" select="text()"/></xsl:call-template>
<xsl:text>"</xsl:text>
</xsl:when>
<xsl:otherwise>""</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="output-string">
<xsl:param name="string" />
<xsl:if test="$string != ''">
<xsl:choose>
<xsl:when test="contains($string, '	') or contains($string, '
') or contains($string, '
') or contains($string, '"') or contains($string, '\')">
<xsl:choose>
<xsl:when test="starts-with($string, '	')">\t</xsl:when>
<xsl:when test="starts-with($string, '
')">\n</xsl:when>
<xsl:when test="starts-with($string, '
')">\r</xsl:when>
<xsl:when test="starts-with($string, '"')">\"</xsl:when>
<xsl:when test="starts-with($string, '\')">\\</xsl:when>
<xsl:otherwise>
<xsl:value-of select="substring($string, 1, 1)"/>
</xsl:otherwise>
</xsl:choose>
<xsl:call-template name="output-string"><xsl:with-param name="string" select="substring($string, 2)"/></xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$string"/>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
本文地址:https://blog.csdn.net/weixin_42297366/article/details/107153202