Учитывая, что
/
) могут, но не обязательно, быть
сбежал в JSON, и это'
вместо "
, чтобы избежать экранирования в строковых значениях 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-скрипта) этот вывод 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:single-quotes
, кажется очень соблазнительной и близкой к помощи, но как использовать эту опцию с xml-to-json()
, мне неясно.map{'method': 'json', 'use-character-maps': map{ '/': '/' }}
как описан Мартином Хонненом, кажется соблазнительной, близкой к помощи, но, опять же, как использовать эту опцию с xml-to-json()
ускользает (ха) от меня.string/@escape
и string/@escape-key
, судя по моему прочтению спец. и подтвержденному экспериментально, здесь не помогут.Связанное предложение с картой символов можно использовать только в том случае, если вы хотите ввести шаг 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\""}]}
Чтобы вставить специальный параметр сериализации Saxon в строковые значения, которые являются фрагментами XML, я думаю, вы могли бы попытаться сначала запустить ввод через режим, который просто выполняет еще один шаг синтаксического анализа и сериализации, только на этот раз как
. => parse-xml-fragment() => serialize(map {
'method': 'xml',
QName('http://saxon.sf.net/', 'single-quotes'): true()
})
С Saxon 9.9 EE в oXygen и
<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 и сериализации, что он полностью отвечает не только на мой заданный вопрос, но и на многие незаданные вопросы. Он достоин углубленного изучения всем, кому нужно сериализовать XML в JSON.