Toolbox
Toolbox

Reputation: 2491

Add attributes to matched parsed json-to-xml map prior to flatten data

I am looking for a way to match each highest level of data, and add specific attributes for that level. Since the attributes will be different and specific to that highest level of data I assume the need of using template. When the attributes has been applied, the data can be flattened.

Note! The high level keys from JSON data is not needed in the produced XML, they are only needed to understand that each high level key group should have specific set of attributes.

To clarify, the current difference between "result" and "wanted result", is that "result" adds the attribute "period0" on all given high-level keys, meanwhile "wanted result" is that each high-level key (e.g. "general", etc) has it's own way of defining it's attributes, prior to being flattened. Added some comments in the "wanted result" for further clarification of origin.

https://xsltfiddle.liberty-development.net/nbiE1a1/2

XML data source file:

<data>
{
    "general": {
      "Language": "English",
      "Country": "Sweden"
    },

    "units-definitions": {
      "SEK": "iso4217:SEK"
    }
  }
</data>

XSL:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="3.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:root="http://www.example.org/1"
  xmlns:flat="http://www.example.org/2"
  exclude-result-prefixes="xs"
  expand-text="yes">

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="data">
    <root:report>
      <xsl:apply-templates select="json-to-xml(.)//*[@key and not(*)]"/>
    </root:report>
  </xsl:template>
  
  <!-- Generic for all flattened data-->
  
  <xsl:template match="*[@key]">
    <xsl:element name="flat:{@key}">
      <xsl:attribute name="contextRef">period0</xsl:attribute>
      <xsl:value-of select="."/>
    </xsl:element>
  </xsl:template>
  
  <!-- Template specific for "general" -->
  
  
  <!-- Template specific for "units-definitions" -->

</xsl:stylesheet>

Result:

<?xml version="1.0" encoding="UTF-8"?>
<root:report xmlns:root="http://www.example.org/1" xmlns:flat="http://www.example.org/2">
   <flat:Language contextRef="period0">English</flat:Language>
   <flat:Country contextRef="period0">Sweden</flat:Country>
   <flat:SEK contextRef="period0">iso4217:SEK</flat:SEK>
</root:report>

Wanted result:

<?xml version="1.0" encoding="UTF-8"?>
<root:report xmlns:root="http://www.example.org/1" xmlns:flat="http://www.example.org/2">
   <!--Origins from "general"-->
   <flat:Language contextRef="period0">English</flat:Language>
   <flat:Country contextRef="period0">Sweden</flat:Country>
   <!--Origins from "units-definitions"-->
   <flat:SEK contextRef="balance0">iso4217:SEK</flat:SEK>
</root:report>

Upvotes: 0

Views: 66

Answers (1)

Martin Honnen
Martin Honnen

Reputation: 167716

So to give you an example using template matching with parameters:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="3.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:root="http://www.example.org/1"
  xmlns:flat="http://www.example.org/2"
  exclude-result-prefixes="xs"
  expand-text="yes">
    
  <xsl:mode on-no-match="shallow-skip"/>

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="data">
    <root:report>
      <xsl:apply-templates select="json-to-xml(.)/*"/>
    </root:report>
  </xsl:template>
  
  <!-- Generic for all flattened data-->
  
  <xsl:template match="*[@key and not(*)]">
    <xsl:param name="contextRef" tunnel="yes"/>
    <xsl:element name="flat:{@key}">
      <xsl:attribute name="contextRef" select="$contextRef"/>
      <xsl:value-of select="."/>
    </xsl:element>
  </xsl:template>
  
  <!-- Template specific for "general" -->
  <xsl:template match="*[@key = 'general']">
    <xsl:apply-templates>
        <xsl:with-param name="contextRef" tunnel="yes" select="'period0'"/>
    </xsl:apply-templates>
  </xsl:template>
  
  <!-- Template specific for "units-definitions" -->

  <xsl:template match="*[@key = 'units-definitions']">
    <xsl:apply-templates>
        <xsl:with-param name="contextRef" tunnel="yes" select="'balance0'"/>
    </xsl:apply-templates>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/nbiE1a1/3

Upvotes: 1

Related Questions