Home > Back-end >  transform external produced json file to xml using XSLT 3
transform external produced json file to xml using XSLT 3

Time:10-17

I have been checking related entries in SO and so far no luck, as my use case seems to have some commonalities but also differences with provided solutions (like: Converting json array to xml using XSLT or Convert JSON to XML using XSLT 3.0 functions).

so hopefully somebody can help me here please.

I call the transformation like this:

java -jar SaxonHE/saxon-he-11.4.jar -s:not_used.xml -xsl:rework_map.xsl -o:report-map.xml p1="list.json"

INPUT: list.json - file produced externally and not embedded in xml, containing array of entries, like:

[
  {
    "tc_id": "A_S_0001",
    "file_name": "\\scripts\\A_S_0001.cs",
    "version": "19",
    "is_automated": true
  },
  {
    "tc_id": "A_S_0002",
    "file_name": "\\scripts\\A_S_0002.cs",
    "version": "25",
    "is_automated": false
  }
]

EXPECTED OUTPUT: something like this:

<list>
<test_case>
<tc_id>A_S_0001</tc_id>
<file_name>\\scripts\\A_S_0001.cs</file_name>
<version>19</version>
<is_automated>true</is_automated>
</test_case>
<test_case>
<tc_id>A_S_0002</tc_id>
<file_name>\\scripts\\A_S_0002.cs</file_name>
<version>25</version>
<is_automated>false</is_automated>
</test_case>
</list>

my template rework_map.xsl (not working)

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:fn="http://www.w3.org/2005/xpath-functions"
    xmlns:math="http://www.w3.org/2005/xpath-functions/math"
    xmlns:map="http://www.w3.org/2005/xpath-functions/map"
    xmlns:array="http://www.w3.org/2005/xpath-functions/array"
    exclude-result-prefixes="xs math map array fn"
    version="3.0">


    <!-- OUTPUT -->
    <xsl:output method="xml" indent="yes"/>
    <!-- PARAMETERS -->
    <xsl:param name="p1"></xsl:param>    <!-- list.json -->

    <!-- VARIABLES -->
    <xsl:variable name="json-array" select="json-doc($p1)"/>

    <xsl:template match="/">
        <!-- <xsl:call-template name="common.INFO"/> -->

        <list>
            <xsl:apply-templates select="$json-array/*"/>

        </list>
    </xsl:template>

    <xsl:template match="fn:map">
        <test_case>
            <xsl:apply-templates/>
        </test_case>
    </xsl:template>

    <xsl:template match="fn:map/fn:*">
        <xsl:element name="{@key}">
            <xsl:value-of select="."/>
        </xsl:element>
    </xsl:template>

</xsl:stylesheet>

CodePudding user response:

One option with Saxon 11 is to feed the JSON files with the -json:list.json option (don't use a -s option) and write code along the lines of

<?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"
  xmlns:map="http://www.w3.org/2005/xpath-functions/map"
  exclude-result-prefixes="#all"
  expand-text="yes">

  <xsl:output indent="yes"/>

  <xsl:template match=".[. instance of array(map(*))]" name="xsl:initial-template">
    <list>
      <xsl:apply-templates select="?*"/>
    </list>
  </xsl:template>
  
  <xsl:template match=".[. instance of map(*)]">
    <test_case>
      <xsl:variable name="map" select="."/>
      <xsl:iterate select="map:keys(.)">
        <xsl:element name="{.}">{$map(.)}</xsl:element>
      </xsl:iterate>
    </test_case>
  </xsl:template>
  
</xsl:stylesheet>

This directly processes the JSON as XPath 3.1 arrays/maps, the disadvantage is that XPath 3.1 maps have no order for the items in them so the result can be e.g.

<list>
   <test_case>
      <version>19</version>
      <is_automated>true</is_automated>
      <file_name>\scripts\A_S_0001.cs</file_name>
      <tc_id>A_S_0001</tc_id>
   </test_case>
   <test_case>
      <version>25</version>
      <is_automated>false</is_automated>
      <file_name>\scripts\A_S_0002.cs</file_name>
      <tc_id>A_S_0002</tc_id>
   </test_case>
</list>

The other option is to start with -it for the initial-template and use json-to-xml and just write templates e.g.

<?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"
  xmlns:fn="http://www.w3.org/2005/xpath-functions"
  exclude-result-prefixes="#all"
  expand-text="yes">

  <xsl:output indent="yes"/>
  
  <xsl:param name="json-string" as="xs:string" select="unparsed-text('list.json'"/>

  <xsl:template name="xsl:initial-template">
    <list>
      <xsl:apply-templates select="json-to-xml($json-string)/*"/>
    </list>
  </xsl:template>
  
  <xsl:template match="fn:map[not(@key)]">
    <test_case>
      <xsl:apply-templates/>
    </test_case>
  </xsl:template>
  
  <xsl:template match="fn:*[@key and not(*)]">
    <xsl:element name="{@key}">{.}</xsl:element>
  </xsl:template>
  
</xsl:stylesheet>
  • Related