XML 到 JSON 有序列表
Posted
技术标签:
【中文标题】XML 到 JSON 有序列表【英文标题】:XML to JSON ordered list 【发布时间】:2021-12-27 19:25:45 【问题描述】:这是我尝试转换为 JSON 的 XML 对象的简化示例。这里的关键是有一组具有不同属性的子节点,其中一些是重复的,并且当它们进入 JSON 时需要保持有序。此外,我无法更改 XML 输入格式。我不在乎,尤其是 JSON 对象采用什么格式。我可以根据需要调整后面的代码,只要 JSON 对象在转换出来时是有序的,并且我仍然可以访问原始 xml 元素名称(添加、搅拌、移动等)
<recipe>
<orderedDirections>
<add what="flour" to="bowl" amount="1c"/>
<add what="sugar" to="bowl" amount="1/2c"/>
<stir what="bowl"/>
<move from="bowl" to="pot" amount="1/2"/>
<add what="eggs" to="pot"/>
<stir what="pot"/>
</orderedDirections>
</recipe>
我目前在 XML 上使用 Newtonsoft.Json.JsonConvert.SerializeObject 来进行转换,尽管我不受该特定算法的约束。当我使用默认设置执行此操作时,我得到:
"recipe":
"orderedDirections":
"add": [
"@what": "flour",
"@to": "bowl",
"@amount": "1c"
,
"@what": "sugar",
"@to": "bowl",
"@amount": "1/2c"
,
"@what": "eggs",
"@to": "pot"
],
"stir": [
"@what": "bowl"
,
"@what": "pot"
],
"move":
"@from": "bowl",
"@to": "pot",
"@amount": "1/2"
显然,这不是我需要的,因为订单在此过程中完全丢失了。我认为我需要做的是让 JsonConverter 把它变成更像这样的东西,但我完全不确定如何到达那里:
"recipe":
"orderedDirections": [
"@verb": "add",
"@what": "flour",
"@to": "bowl",
"@amount": "1c"
,
...
"@verb": "stir",
"@what": "pot"
]
JsonConverter 是正确的轨道吗?是否有一些我可以覆盖的属性或设置可以在我不必过于具体的情况下实现这一点?
更新要求: 这些不是 XML 文档/模式中唯一的节点,只是给我带来麻烦的唯一节点。我目前正在使用:
var recipeDoc = XmlDocument.LoadDocument("recipe.xml");
var json = Newtonsoft.Json.JsonConvert.SerializeXmlNode(recipeDoc);
这将为 XML 中的所有其他 40-50 个元素生成可用/正确的 json。我不介意为orderedDirections 节点(JsonConverter、XSLT 等)编写转换规范,但我想保留其他所有内容的默认值而不必明确指定它,包括orderedDirections 的子节点,它们实际上是比我在这个例子中列出的要复杂。
【问题讨论】:
【参考方案1】:大多数人不想要普通的 XML 到 JSON 的转换,他们想要从特定 XML 表单到特定 JSON 表单的自定义转换,为此您需要能够编写详细的规则。 XSLT 3.0 提供了一个合适的模板引擎:
<xsl:output method="json" indent="yes"/>
<xsl:template match="/">
<xsl:map>
<xsl:map-entry key="recipe">
<xsl:map>
<xsl:map-entry key="orderedDirections">
<xsl:array>
<xsl:apply-templates select="//orderedDirections/*"/>
</xsl:array>
</xsl:map-entry>
</xsl:map>
</xsl:map-entry>
</xsl:map>
</xsl:template>
<xsl:template match="orderedDirections/*">
<xsl:map>
<xsl:map-entry key="'@verb'" select="local-name()"/>
<xsl:apply-templates select="@*"/>
</xsl:map>
</xsl:template>
<xsl:template match="orderedDirections/*/@*">
<xsl:map-entry key="'@'||local-name()" select="string(.)"/>
</xsl:template>
(xsl:array
指令是 XSLT 3.0 规范中令人尴尬的遗漏,但您会在 Saxon [免责声明:我的产品] 中找到它,如果您想遵守标准,还有一些变通方法)。
【讨论】:
是否可以仅为orderedDirections 元素定义XSLT?该元素只是一个更大的 XML 文档中的一个,也是我正在使用的原版转换中唯一一个出现错误的元素。我不想为整个事情定义一个 XSLT。 设置通用模板规则来重现“香草”行为应该不难。但我不知道“香草”行为是什么,例如您的转换器对 XML 命名空间的作用。周围有很多转换器,他们都以不同的方式解决这些问题。 我已经更新了我原来的问题。我也不确切地知道所有的香草规则是什么,我真的不想为此重新发明***。以上是关于XML 到 JSON 有序列表的主要内容,如果未能解决你的问题,请参考以下文章
Alamofire 是不是支持结构化为有序值列表的 JSON?参数为 [String: Any],仅符合名称/值对的集合