xslt-2.0xslt-3.0

parse value from JSON structure in the xml input


I want to parse the values from XML input which contains JSON structure value I need to read each value from JSON structure mentioned as a value in XML

Example of my XML

<?xml version='1.0' encoding='UTF-8'?>
<root>
    <UnitId>db338737-f7</UnitId>
    <InputParameters>
        <key>D01</key>
        <value>Default Work Order Type</value>
    </InputParameters>
    <InputParameters>
        <key>CanonicalMessage</key>
        <value>{"OperationName":"ServiceOrder","Payload":{"Title":"grid VII","ID":"1008"}}</value>
    </InputParameters>
</root>

XSLT code which I built to read whole value of JSON

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>
    <xsl:template match="/root">
        <A_ServicerOrder>
            <A_ServicerOrderType>
                <ServiceOrderType>
                    <xsl:value-of select="'YRVO'"/>
                </ServiceOrderType>
                <xsl:for-each select="InputParameters">
                    <xsl:if test="key  = 'CanonicalMessage'">
                        <xsl:variable name="description">
                            <xsl:value-of select="value"/>
                        </xsl:variable>
                        <OperationName>
                        <xsl:value-of select="$description"/>
                        </OperationName>
                        <ServiceOrderDescription>
                            <xsl:value-of select="$description"/>
                        </ServiceOrderDescription>
                    </xsl:if>
                </xsl:for-each>
            </A_ServicerOrderType>
        </A_ServicerOrder>
    </xsl:template>

I would like to read each value from ({"OperationName":"ServiceOrder","Payload":{"Title":"grid VII","ID":"1008"}}) If (Key = Canonical Message)

How to provide this kind of logic in XSLT?

Output expected:

<?xml version="1.0" encoding="UTF-8"?>
<A_ServicerOrder>
   <A_ServicerOrderType>
      <ServiceOrderType>YRVO</ServiceOrderType>
      <OperationName>ServiceOrder</OperationName>
      <CaseTitle>grid VII</CaseTitle>
      <AssetNumber>1008</AssetNumber>
   </A_ServicerOrderType>
</A_ServicerOrder>

Solution

  • You can use the XPath 3.1 function parse-json to parse the JSON into an XDM 3.1 map and then you can use the XPath 3.1 lookup operator ? to select properties from the map:

    <?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"
      exclude-result-prefixes="#all"
      expand-text="yes">
      
      <xsl:template match="/root">
          <A_ServicerOrder>
                <A_ServicerOrderType>
                    <ServiceOrderType>YRVO</ServiceOrderType>
                    <xsl:apply-templates/>
                </A_ServicerOrderType>
          </A_ServicerOrder>
      </xsl:template>
      
      <xsl:template match="InputParameters[key = 'CanonicalMessage']">
        <xsl:variable name="json" select="parse-json(value)"/>
        <OperationName>{$json?OperationName}</OperationName>
        <CaseTitle>{$json?Payload?Title}</CaseTitle>
        <AssetNumber>{$json?Payload?ID}</AssetNumber>
      </xsl:template>
      
      <xsl:output indent="yes"/>
    
      <xsl:mode on-no-match="shallow-skip"/>
      
    </xsl:stylesheet>
    

    XSLT 3 online fiddle with the sample code.