Jim C Jim C - 4 months ago 6
JSON Question

how transform from xml to json with xsl and removing the item/record labels

Thanks to the excellent answer provided by Tim C in how transform from xml based on attributes to json and ignore the attributes from especific elements by using XLST/XLS, I could learn how to transform my input xml to a json and excluding the item attributes during transformation. Kindly, see the input xml file below.

Please, how can I do exact same transformation but ignoring the "aa" and "bbb" in the output json? I mean, how do I exclude during xml transformation to json the record identifiers named aa and bbb in my case?

In my real world, aa will be always two numeric digits (e.g. 99) standing for certain type of items and bbb will be always three numeric digits (e.g. 999) standing for other type of items. Each product is a sum of some aa plus some bbb type of product. Since the number of the digits tell me exactly if it is aa type or bbb type, I understand that I can have a json otuput file valid both from json and my business perspectives getting an outcome without "aa" and "bbb" words.

input file:

<c:product xmlns:c="myapp">
<c:item cod="789">
<c:aa name="024" value="123"/>
<c:bbb name="0105" value="123456"/>
<c:bbb name="0122" value="T"/>
<c:aa name="071" value="00000001"/>
</c:item>
<c:item package="123" cod="11111">
<c:aa name="002" value="753"/>
<c:aa name="003" value="456"/>
<c:bbb name="0146" value="147852"/>
</c:item>
</c:product>


my current output file when my current XSL is applied:

[
{
"aa" : {"024":"123"},
"bbb" : {"0105":"123456"},
"bbb" : {"0122":"T"},
"aa" : {"071":"00000001"}
},
{
"aa" : {"002":"753"},
"aa" : {"003":"456"},
"bbb" : {"0146":"147852"}
}
]


my current XSL:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:c="myapp" exclude-result-prefixes="c">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>

<xsl:template match="*[c:item]">
<xsl:text>[&#10;</xsl:text>
<xsl:apply-templates select="c:item"/>
<xsl:text>]&#10;</xsl:text>
</xsl:template>

<xsl:template match="c:item">
<xsl:text> {&#10;</xsl:text>
<xsl:apply-templates />
<xsl:text> }</xsl:text>
<xsl:if test="following-sibling::c:item">
<xsl:text>,</xsl:text>
</xsl:if>
<xsl:text>&#10;</xsl:text>
</xsl:template>

<xsl:template match="c:item/*">
<xsl:text> "</xsl:text>
<xsl:value-of select="local-name()" />
<xsl:text>" : {"</xsl:text>
<xsl:value-of select="@name" />
<xsl:text>":"</xsl:text><xsl:value-of select="@value" />
<xsl:text>"}</xsl:text>
<xsl:if test="following-sibling::*">
<xsl:text>,</xsl:text>
</xsl:if>
<xsl:text>&#10;</xsl:text>
</xsl:template>
</xsl:stylesheet>


my desired output that I understand it is both business and json pattern valid :

[
{
{"024":"123"},
{"0105":"123456"},
{"0122":"T"},
{"071":"00000001"}
},
{
{"002":"753"},
{"003":"456"},
{"0146":"147852"}
}
]

Answer

The expected output you give is not valid JSON. Perhaps you want something like this

[
  {
    "024":"123",
    "0105":"123456",
    "0122":"T",
    "071":"00000001"
  },
  {
    "002":"753",
    "003":"456",
    "0146":"147852"
  }
]

With this as your target, it is straight-forward to tweak the XSLT to produce te desired results. The only change is to change the template that matches c:item/* to remove the output of local-name() (which outputs the name of the elements; aaa, bb, etc) and the surrounding braces.

Try this XSLT:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  version="1.0" 
                xmlns:c="myapp" exclude-result-prefixes="c">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>

<xsl:template match="*[c:item]">
    <xsl:text>[&#10;</xsl:text>
    <xsl:apply-templates select="c:item"/>
    <xsl:text>]&#10;</xsl:text>
</xsl:template>

<xsl:template match="c:item">
    <xsl:text>  {&#10;</xsl:text>
        <xsl:apply-templates />
    <xsl:text>  }</xsl:text>
    <xsl:if test="following-sibling::c:item">
        <xsl:text>,</xsl:text>
    </xsl:if>
    <xsl:text>&#10;</xsl:text>
</xsl:template>

<xsl:template match="c:item/*">
        <xsl:text>    "</xsl:text>
        <xsl:value-of select="@name" />
        <xsl:text>":"</xsl:text><xsl:value-of select="@value" />
        <xsl:text>"</xsl:text>
        <xsl:if test="following-sibling::*">
            <xsl:text>,</xsl:text>
        </xsl:if>
        <xsl:text>&#10;</xsl:text>
</xsl:template>
</xsl:stylesheet>

Do take time to study this answer, to understand what each part is doing. Using http://xsltransform.net/ to modify the XSLT would help as you can easily then see what the outcome of each change is.

Comments