Toolbox
Toolbox

Reputation: 2493

Cannot get out value from JSON data

Parsing JSON data in XSLT and attempting to get a specified keys value. I have controlled in the XML map that XSLT produces as part of parsing JSON and I do find the key with value "car".

Problem: I do not get the expected value in the result.

You find the code here: xsltfiddle

Same code is added here:

JSON:

<data>
{
  "storage": {
    "car": "Volvo"
  }
}
</data>

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="xml" indent="yes" html-version="5"/>
    
    <!-- Block all data that has no user defined template -->
    <xsl:mode on-no-match="shallow-skip"/>
    
    <!-- Transform JSON to XML -->
    <xsl:template match="data">
      <xsl:apply-templates select="json-to-xml(.)/*"/>
      <!-- Select -->
      <xsl:value-of select="//*[@key='car']"/>
    </xsl:template>
    
    <!-- Print map -->
  
  <!--  
  <xsl:template match="*[@key = 'storage']"> 
    <xsl:copy-of select=".."/> 
  </xsl:template> 
  -->
  
</xsl:stylesheet>

Result

<?xml version="1.0" encoding="UTF-8"?>

Wanted result

<?xml version="1.0" encoding="UTF-8"?>
Volvo

Upvotes: 0

Views: 150

Answers (3)

Michael Kay
Michael Kay

Reputation: 163352

You wrote in a comment:

Still don't understand though why my code does not work

And indeed, we often make the mistake of giving you code that works, without telling you what you did wrong.

Your mistake is here:

   <xsl:apply-templates select="json-to-xml(.)/*"/>
   <xsl:value-of select="//*[@key='car']"/>

You have two instructions, and you're expecting the second instruction to operate on the result of the first. But that's not how XSLT works; each of these instructions works on the same input (specifically, each of them takes the data element in the source document as input). So //*[@key='car'] doesn't select anything, because there's nothing that matches this in the original source document.

If you want the second instruction to apply to the result of the first, you can put the result of the first in a variable:

<xsl:variable name="converted-input">
   <xsl:apply-templates select="json-to-xml(.)/*"/>
</xsl:variable>
<xsl:value-of select="$converted-input//*[@key='car']"/>

or, as @sspsujit has done, you can collapse it all into a single instruction, because the xsl:apply-templates isn't actually doing anything of interest.

Upvotes: 1

Michael Kay
Michael Kay

Reputation: 163352

I wouldn't convert the JSON to XML for this: I would parse it to an XDM map, and then lookup the value in the map. Thus:

<xsl:value-of select="parse-json(.)?storage?car"/>

Upvotes: 2

sspsujit
sspsujit

Reputation: 301

I think you need this:

<!-- Transform JSON to XML -->
<xsl:template match="data">
  <!-- Select -->
  <xsl:value-of select="json-to-xml(.)//*[@key='car']"/>
</xsl:template>

to get:

<?xml version="1.0" encoding="UTF-8"?>Volvo

Upvotes: 1

Related Questions