XML 在 JSON 中序列化,没有过度转义

XML serialization in JSON without excessive escaping

如何避免 JSON 中 XML 的斜线和双引号转义?

鉴于

  1. solidus 字符(又名 正斜杠 /)可以但不必是 在 JSON 中逃脱,然后
  2. XML 属性可以使用 ' 而不是 " 以避免在 JSON 字符串值中转义,

在 XSLT 中实现这些潜在的序列化改进的最佳方式是什么?


这个XML,

<?xml version="1.0" encoding="UTF-8"?>
<map xmlns="http://www.w3.org/2005/xpath-functions">
  <array key="o_array">
    <map>
      <string key="s/1">x/y/z</string>
    </map>
    <map>
      <string key="s2"><![CDATA[<a href="/x/y">Link</a> a/b "test"]]></string>
    </map>
  </array>
</map>

输入此 XSLT,

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">
  <xsl:output method="text"/>  
  <xsl:template match="/">
    <xsl:value-of select="xml-to-json(.,map{'indent':true()})"/>
  </xsl:template>
</xsl:stylesheet>

产量(通过 Saxon,XSLT Fiddle demo)这个 JSON 输出:

{ "o_array" : 
  [ 
    { "s\/1" : "x\/y\/z" },

    { "s2" : "<a href=\"\/x\/y\">Link<\/a> a\/b \"test\"" } ] }

出于美观的目的(JSON 之上是不必要的丑陋)和最小化文件大小(同时禁用缩进),我想生成以下 JSON 改为:

{ "o_array" : 
  [ 
    { "s/1" : "x/y/z" },

    { "s2" : "<a href='/x/y'>Link</a> a/b \"test\"" } ] }

备注:

如果您愿意引入一个parse-json() => serialize(...)步骤,则只能使用带有字符映射的链接建议:

. => xml-to-json() => parse-json() => serialize(map { 'method' : 'json', 'use-character-maps' : map { '/' : '/' } })

这样,

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="3.0">

  <xsl:output method="text"/>

  <xsl:template match="/">
      <xsl:value-of select=". => xml-to-json() => parse-json() => serialize(map { 'method' : 'json', 'use-character-maps' : map { '/' : '/' } })"/>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/b4GWVd/25 我得到

{"o_array":[{"s/1":"x/y/z"},{"s2":"<a href=\"/x/y\">Link</a> a/b \"test\""}]}

要在 XML 片段的字符串值上插入 Saxon 特定的序列化参数,我认为您可以尝试 运行 首先通过一种简单地执行另一个解析和序列化步骤的模式输入,仅这次是

. => parse-xml-fragment() => serialize(map {
                        'method': 'xml',
                        QName('http://saxon.sf.net/', 'single-quotes'): true()
                    })

使用氧气中的 Saxon 9.9 EE 和

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">

    <xsl:output method="text"/>

    <xsl:template match="/">
        <xsl:value-of
            select="
                $single-quotes => xml-to-json() => parse-json() => serialize(map {
                    'method': 'json',
                    'use-character-maps': map {'/': '/'}
                })"
        />
    </xsl:template>

    <xsl:variable name="single-quotes">
        <xsl:apply-templates mode="serialize-fragments"/>
    </xsl:variable>

    <xsl:mode name="serialize-fragments" on-no-match="shallow-copy"/>

    <xsl:template match="string" mode="serialize-fragments"
        xpath-default-namespace="http://www.w3.org/2005/xpath-functions">
        <xsl:copy>
            <xsl:apply-templates select="@*" mode="#current"/>
            <xsl:try
                select="
                    . => parse-xml-fragment() => serialize(map {
                        'method': 'xml',
                        QName('http://saxon.sf.net/', 'single-quotes'): true()
                    })">
                <xsl:catch select="string()"/>
            </xsl:try>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

我明白了

{"o_array":[{"s/1":"x/y/z"},{"s2":"<a href='/x/y'>Link</a> a/b \"test\""}]}