xml - 在不使用任何硬编码元素的情况下,使用 XSLT 1.0 将给定的 xml 概括为 json 的正确方法是什么?
问题描述
我正在处理以下 XML 文档,我想在其中将 XML 转换为 JSON。
<?xml version="1.0" encoding="UTF-8"?>
<DATA>
<CATEGORY>
<COUNT> 5 </COUNT>
</CATEGORY>
<TYPE>
<COUNT> 10 </COUNT>
</TYPE>
<FRUITS>
<NAME>APPLE</NAME>
<FRUIT_COUNT>10</FRUIT_COUNT>
</FRUITS>
<FRUITS>
<NAME>ORANGES</NAME>
<FRUIT_COUNT>20</FRUIT_COUNT>
</FRUITS>
</DATA>
我要为上述 XML 转换为的 JSON 如下所示。
{
"CATEGORY":5,
"TYPE": 10,
"FRUITS":{
"APPLE": 10,
"ORANGES": 20
}
}
所以我编写了下面的 XSLT 代码来将上面的 XML 转换为 JSON。
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text"/>
<xsl:template match="/DATA">
<xsl:text>{"CATEGORY":</xsl:text>
<xsl:value-of select="CATEGORY/COUNT"/>
<xsl:text>,</xsl:text>
<xsl:text>"TYPE":</xsl:text>
<xsl:value-of select="TYPE/COUNT"/>
<xsl:text>,</xsl:text>
<xsl:text>
"FRUITS": {
</xsl:text>
<xsl:for-each select="FRUITS">
<xsl:text>"</xsl:text>
<xsl:value-of select="NAME"/>
<xsl:text>":</xsl:text>
<xsl:value-of select="FRUIT_COUNT"/>
<xsl:if test="position()!=last()">,</xsl:if>
</xsl:for-each>
<xsl:text>}}</xsl:text>
</xsl:template>
</xsl:stylesheet>
上面的 XSLT 按预期将 XML 转换为 JSON。但是,我无法概括上述 XSLT,因此如果添加了新字段,我不必像在上述 XSLT 中那样对其进行硬编码。什么是概括 XSLT 以便它在没有硬编码的情况下创建 JSON 的正确方法?在概括它时我做错了什么吗?
更新:
我尝试使用以下 XSLT 概括 XSLT 以将 XML 转换为 JSON:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text"/>
<xsl:template match="/DATA">
<xsl:text>{</xsl:text>
<xsl:for-each select="/DATA">
<xsl:for-each select="*">
<xsl:text>"</xsl:text><xsl:value-of select="local-name()"/><xsl:text>":</xsl:text><xsl:value-of select="."/>
<xsl:if test="position()!=last()">,</xsl:if>
</xsl:for-each>
</xsl:for-each>
<xsl:text>}</xsl:text>
</xsl:template>
</xsl:stylesheet>
但是当我使用上述 XSLT 时的输出如下:
{"CATEGORY":
5
,"TYPE":
10
,"FRUITS":
APPLE
10
,"FRUITS":
ORANGES
20
}
我如何概括嵌套的 JSON,以便我可以获得正确格式的 JSON。在修改后的转换后的 JSON 中,我得到了两次“FRUITS”,它不是我想要实现的嵌套格式。
解决方案
确实没有正确的方法来概括这一点。你可能需要想出一套你想要实施的规则,并以此为基础。
- 如果根元素的子元素
DATA
没有 aNAME
,则将该元素作为属性输出,其名称为元素名称,文本值作为其值。 - 如果子元素确实有
NAME
,则使用元素名称的名称输出单个属性,并且对于具有相同名称的所有元素,输出基于 的嵌套属性NAME
。
在这种情况下,您可以像这样编写 XSLT:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text"/>
<xsl:template match="DATA" priority="2">
<xsl:text>{</xsl:text>
<xsl:apply-templates />
<xsl:text>}</xsl:text>
</xsl:template>
<xsl:template match="*[not(NAME)]">
<xsl:text>"</xsl:text>
<xsl:value-of select="name()" />
<xsl:text>":</xsl:text>
<xsl:value-of select="normalize-space()"/>
<xsl:text>,</xsl:text>
</xsl:template>
<xsl:template match="*[NAME][1]">
<xsl:text>"</xsl:text>
<xsl:value-of select="name()" />
<xsl:text>": {</xsl:text>
<xsl:for-each select="../*[name() = name(current())]">
<xsl:text>"</xsl:text>
<xsl:value-of select="NAME"/>
<xsl:text>":</xsl:text>
<xsl:value-of select="*[not(self::NAME)]"/>
<xsl:if test="position()!=last()">,</xsl:if>
</xsl:for-each>
<xsl:text>}</xsl:text>
</xsl:template>
<xsl:template match="*[NAME][position() > 1]" />
</xsl:stylesheet>
推荐阅读
- flutter - 如何在颤动的图像中插入可点击点?
- java - 连接spring boot应用程序和google Cloud SQL的推荐方式是什么?
- python - Kivy: UnicodeEncodeError: 'gbk' codec can't encode character '\u017c' in position 256: 非法多字节序列
- api-platform.com - 带有计算列的 Api 平台过滤器(即地理距离)
- javascript - Javascript chai 为什么抛出没有被抓到?
- javascript - Javascript 问题:检查输入框中是否包含单词的脚本。仅全词
- amazon-s3 - AWS Lambda 不会将文件从一个 s3 存储桶复制到云中的另一个存储桶,但在本地它可以工作
- .net - .NET STANDARD 4.7.2 Azure 承载令牌授权
- go - 如何使用 unmarshal 解析 gpx
- rest - 邮差奇异 401