MrD at KookerellaLtd
MrD at KookerellaLtd

Reputation: 2807

controlling serialisation of xml inside JSON

xslt 3.0 saxon PE 11.4

I've got this to work, but by accident.

Consider this input.

<?xml version="1.0" encoding="UTF-8"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet">
</Workbook>

and I want to get to this JSON (encodings are hard...so I think I NEED to escape the '"' char, and I'm not too worried about the JSON escaping of '/')

{
   "xmlData": "<Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\"><\/Workbook>"
}

so basically some external psuedo code can go.

json = JSON.Read("file.json")
xmlString = json["xmlDate"]
xml = XDocument.Parse(xmlString)

and the xml is read into some xml model.

so my attempt is this.

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:map="http://www.w3.org/2005/xpath-functions/map"
    xmlns:array="http://www.w3.org/2005/xpath-functions/array"
    exclude-result-prefixes="map array">
    <xsl:output method="json"/>
    
    <xsl:template match="/">
        <xsl:variable name="transformed-xml">
            <xsl:copy-of select="."/>
        </xsl:variable>
        
        <xsl:map>
            <xsl:map-entry key="'xmlData'" select="serialize($transformed-xml)"/>
        </xsl:map>
    </xsl:template>
</xsl:stylesheet>

1st try

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:map="http://www.w3.org/2005/xpath-functions/map"
    xmlns:array="http://www.w3.org/2005/xpath-functions/array"
    exclude-result-prefixes="map array">
    <xsl:output method="json"/>
    
    <xsl:template match="/">
        <xsl:variable name="transformed-xml">
            <xsl:copy-of select="."/>
        </xsl:variable>
        
        <xsl:variable name="json-string">
            <!-- Convert the transformed XML to a JSON string -->
            <xsl:value-of select="serialize($transformed-xml)"/>
        </xsl:variable>
        
        <xsl:map>
            <xsl:map-entry key="'xmlData'" select="$json-string"/>
        </xsl:map>
    </xsl:template>
</xsl:stylesheet>

gives me this

{
   "xmlData": "&lt;Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\"&gt;\n&lt;\/Workbook&gt;"
}

nasty...its 'xml' escaped the '<','>', and the new line...not 100% sure why, I assume serialise is escaping the string into 'xml' format, because its embedding a 'text' node inside a document-node?

ok...try 2

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:map="http://www.w3.org/2005/xpath-functions/map"
    xmlns:array="http://www.w3.org/2005/xpath-functions/array"
    exclude-result-prefixes="map array">
    <xsl:output method="json"/>
    
    <xsl:template match="/">
        <xsl:variable name="transformed-xml">
            <xsl:copy-of select="."/>
        </xsl:variable>
        
        <xsl:map>
            <xsl:map-entry key="'xmlData'" select="serialize($transformed-xml)"/>
        </xsl:map>
    </xsl:template>
</xsl:stylesheet>

gives

{
   "xmlData": "<Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\">\n<\/Workbook>"
}

which works! because its not 1st embedding it in a text node inside a document node?

P.S. I assume this is a sensible way to do this that wont bite me later?

Upvotes: 0

Views: 74

Answers (1)

Martin Honnen
Martin Honnen

Reputation: 167716

JSON output can serialize nodes so

<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="map { 'xmlData' : . }"/>
  </xsl:template>
  
</xsl:stylesheet>

gives e.g. (Saxon HE 12.3)

{ "xmlData":"<Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\">\n<\/Workbook>" }

There is also a serialization attribute https://www.w3.org/TR/xslt-xquery-serialization-31/#JSON_JSON-NODE-OUTPUT-METHOD to control the node serialization method used for nodes serialized as part of the json output method.

So basically I am not sure why you attempt to serialize the XML in your own code.

Upvotes: 1

Related Questions