【问题标题】:XML serialization in JSON without excessive escapingJSON 中的 XML 序列化,无需过度转义
【发布时间】:2019-10-16 04:47:35
【问题描述】:

如何避免 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\"" } ] }

注意事项:

  • 单引号: Saxon 特定的序列化选项saxon:single-quotes 似乎很有帮助,但我不清楚如何将此选项与xml-to-json() 一起使用。
  • Solidus: XSLT 序列化选项 map{'method': 'json', 'use-character-maps': map{ '/': '/' }}described by Martin Honnen 似乎很有帮助,但同样,如何将此选项与 xml-to-json() 一起使用让我感到困惑(哈哈)。
  • string/@escapestring/@escape-key 属性,根据我对spec 的阅读并通过实验确认,在这里无济于事。

【问题讨论】:

    标签: json xml xslt saxon xslt-3.0


    【解决方案1】:

    如果您愿意引入parse-json() =&gt; 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()
                        })
    

    在 oXygen 中使用 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\""}]}
    

    【讨论】:

    • 高手!这个答案采用了许多令人印象深刻的 XSLT 3.0 JSON 和序列化技术,它不仅完全回答了我提出的问题,而且还回答了许多未提出的问题。值得任何需要在 JSON 中序列化 XML 的人深入研究。
    猜你喜欢
    • 1970-01-01
    • 2020-07-09
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-23
    相关资源
    最近更新 更多