提问人:ssdev 提问时间:10/21/2023 更新时间:10/21/2023 访问量:99
使用 XSLT 分析未包装的 json
Using XSLT to parse non-wrapped json
问:
在我见过的所有将 json 转换为 xml 的 xslt 示例中,json 在使用 json-to-xml() 函数进行处理之前总是包装在 xml 标记中。我很好奇是否可以在不包装 json 的情况下进行转换。我一直在玩这个 xslt 小提琴无济于事,但是如果我把它包装起来,然后将输入类型更改为 xml,它就可以了。有没有人对如何让小提琴中的 xslt 与裸 json 一起工作有任何指导?<data></data>
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all">
<xsl:template match="/">
<xsl:copy-of select="json-to-xml(.)"/>
</xsl:template>
</xsl:stylesheet>
答:
我不知道 Fiddle 是如何调用 Saxon 的,但我怀疑当您选择输入类型作为 JSON 时,它实际上会解析 JSON 并提供映射和数组的结果结构作为初始上下文项。不幸的是,json-to-xml() 函数需要未解析的词法 JSON 作为输入,因此我唯一可以做到这一点的方法是重新序列化 JSON,如下所示:
<xsl:template match=".">
<xsl:copy-of select="serialize(.,
map{'method':'json'}) => json-to-xml()"/>
</xsl:template>
请注意 而不是 ,因为 “/” 将仅匹配 XML 文档的根,而 “.” 将匹配任何内容。match="."
match="/"
如果不受 Fiddle 实现方式的限制,则可以将 JSON 内容作为字符串或文件的 URI 提供给样式表,可以使用 .unparsed-text()
评论
<xsl:copy-of select="json-to-xml(unparsed-text())"/>
xsl:initial-template
unparsed-text($fileName)
unparsed-text
content
json-to-xml($jsonString)
如果您选择输入类型JSON,则小提琴确实会将输入编辑器中的JSON解析为XPath 3.1 XDM映射或数组。所以我想说它适用于原始 JSON,在 XSLT 3/XPath 3.1 使用的表示中。但是,您的XSLT必须考虑到这一点,尝试匹配XML文档节点,它永远不会匹配表示JSON的XDM映射或数组;您可以使用它来匹配任何项目,因此标识“原始”JSON 到 JSON 将在这个小提琴上,例如parse-json
match="/"
match="."
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all">
<xsl:output method="json" indent="yes"/>
<xsl:template match=".">
<xsl:sequence select="."/>
</xsl:template>
</xsl:stylesheet>
从“原始”JSON 到 JSON 的转换,递增 id 是在这个小提琴上,例如
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:map="http://www.w3.org/2005/xpath-functions/map"
exclude-result-prefixes="#all">
<xsl:output method="json" indent="yes"/>
<xsl:template match=".">
<xsl:sequence select="map:put(., 'contents', array { ?contents?* ! map:put(., 'id', ?id + 1) })"/>
</xsl:template>
</xsl:stylesheet>
至于应用的意图,Michael已经解释过,由于该函数不适用于JSON的XDM表示形式,如地图或数组,而是适用于JSON的字符串输入,因此您需要序列化为JSON,然后应用,如接受的答案所示。json-to-xml
json-to-xml
我的小提琴和 SaxonJS 都没有选择直接使用文本文件的字符串内容作为上下文项,但是 BaseX 小提琴可以做到这一点,因此,使用正确的上下文类型文本,您可以使用.json-to-xml(.)
我还更新了 XSLT 3、SaxonJS 2 驱动的小提琴以允许纯文本输入,因此如果您使用 JSON 输入数据但将其视为纯文本,就像在这个小提琴中一样,您确实可以使用.json-to-xml(.)
评论