Search code examples
jsonxmlxsltxml-parsingxslt-1.0

XSLT replacing Json with plain text equivelent


Hey all I am newish at XSLT and have a XSLT output that contains some json within elements.

I've been looking around to see if there is anyway for XSLT to replace the json with just a string:

Ex:

<company:Cause 
   xmlns:company="http://example.com/company" 
   xmlns:j="http://example.com/j" 
   xmlns:s="http://example.com/s" 
   xmlns:nc="http://example.com/nc"
>
   <j:Cause s:id="Cause-08D628B86EF2">
      <nc:DescriptionText>{"code":"PC","description":"Probable Cause"}</nc:DescriptionText>
      <nc:ActivityDate>
         <nc:DateTime>2018-10-02T00:00:00</nc:DateTime>
      </nc:ActivityDate>
      <j:Name>{"code":"PC","description":"Probable Cause"}</j:Name>
      <company:Augmentation>
         <j:Stat>
            <j:DescriptionText>{"code":"PC","description":"Probable Cause"}</j:DescriptionText>
         </j:Stat>
      </company:Augmentation>
   </j:Cause>
</company:Cause>

Is there anything I can add to the XSLT in order to do this on the fly? Anything already built into XSLT?


Solution

  • If you're stuck with XSLT 1.0, and you wanted to process JSON properly, tt would certainly be possible to build a full JSON parser using recursive named templates, but that may be overkill. Much simpler to do as y.arazim suggests and just strip out the "special" JSON characters by translating them all into spaces, and then use the normalize-space() function to convert each run of multiple spaces into a single space. e.g.

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
       xmlns:company="http://example.com/company" 
       xmlns:j="http://example.com/j" 
       xmlns:s="http://example.com/s" 
       xmlns:nc="http://example.com/nc"
    >
    
      <!-- identity template copies anything that doesn't need munging -->
      <xsl:template match="*|@*">
        <xsl:copy>
          <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
      </xsl:template>
      
      <!-- these elements are munged to remove special JSON characters -->
      <xsl:template match="j:Name | j:DescriptionText | nc:DescriptionText">
        <xsl:variable name="unwanted-characters">{":,}</xsl:variable>
        <xsl:copy>
          <xsl:apply-templates select="@*"/>
          <xsl:value-of select="
            normalize-space(
              translate(., $unwanted-characters, '       ')
            )
          "/>
        </xsl:copy>
      </xsl:template>
    
    </xsl:stylesheet>
    

    NB the string of spaces which appears as the third parameter to the translate() function should be the same length (or longer!) than the second parameter (containing the unwanted characters). The translate() function takes the first parameter and for each character in that string it looks for that character in the second parameter, and if it's found, it replaces it with the character at the same position in the third parameter. So the third parameter being entirely spaces means that every one of those unwanted characters will be replaced with a space.

    Result:

    <company:Cause xmlns:company="http://example.com/company" xmlns:j="http://example.com/j" xmlns:nc="http://example.com/nc" xmlns:s="http://example.com/s">
       <j:Cause s:id="Cause-08D628B86EF2">
          <nc:DescriptionText>code PC description Probable Cause</nc:DescriptionText>
          <nc:ActivityDate>
             <nc:DateTime>2018-10-02T00:00:00</nc:DateTime>
          </nc:ActivityDate>
          <j:Name>code PC description Probable Cause</j:Name>
          <company:Augmentation>
             <j:Stat>
                <j:DescriptionText>code PC description Probable Cause</j:DescriptionText>
             </j:Stat>
          </company:Augmentation>
       </j:Cause>
    </company:Cause>
    

    NB you will need to use the proper namespace URIs rather than the dummy values I added here.