1

I believe my question provides a good idea what I am trying to do. BTW, find below the incoming xml and desired json output.

I found an excellent answer here Problems converting XML to JSON using XSLT about how to move from xml to json but my xml is a bit different. Kindly, note below that the values are part of the attributes. Additionally, I want to ignore the attributes from c:item. In other words, cod and package must be ignored. I know how to transform such xml based on attributes to another xml based on element values and then transform this new xml in json format but it seems to me a bit strange the first step (from xml to another xml) since I want the json only. I know from xml to xml thanks to the excellent answer just provided here while transforming attributes to element with XSLT how ignore only the attributes in parent element

incoming xml

<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>

output xml just to exemplify the extra step I have to do with my current knolege, i.e, if I am obligated to do the extra step from xml to xml just to take out the attributes from c:item and formating the values as element instead of attributes before going from xml to json

<product>
   <item>
      <aa>
         <name>024</name>
         <value>123</value>
      </aa>
      <bbb>
         <name>0105</name>
         <value>123456</value>
      </bbb>
      <bbb>
         <name>0122</name>
         <value>T</value>
      </bbb>
      <aa>
         <name>071</name>
         <value>00000001</value>
      </aa>
   </item>
   <item>
      <aa>
         <name>002</name>
         <value>753</value>
      </aa>
      <aa>
         <name>003</name>
         <value>456</value>
      </aa>
      <bbb>
         <name>0146</name>
         <value>147852</value>
      </bbb>
   </item>
</product>

the current xls used for transform from xml to xml

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:c="myapp"
exclude-result-prefixes="c">
<xsl:output method="xml" omit-xml-declaration="yes" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="*">
    <xsl:element name="{local-name()}">
        <xsl:apply-templates select="@*|node()"/>
    </xsl:element>
</xsl:template>

<xsl:template match="c:item">
    <xsl:element name="{local-name()}">
        <xsl:apply-templates/>
    </xsl:element>
</xsl:template>

<xsl:template match="@*">
    <xsl:element name="{local-name()}">
        <xsl:value-of select="."/>
    </xsl:element>
</xsl:template>

</xsl:stylesheet>

outcome and desired json (well just imagine the last xml transformed in a json file)

    {
       {
         "aa" : {"024":"123"}
         "bbb" : {"0105","123456"}
         "bbb" : {"0122","T"}
         "aa" : {"071","00000001"}
       }
   {
       {
       ...
       }
   }

**** Edited July 31th

output based on Michael Kay answer:

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

XLS used based on Michael Kay answer and generating above outcome

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:c="myapp" exclude-result-prefixes="c">
<xsl:output method="xml" omit-xml-declaration="yes" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<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:template>
</xsl:stylesheet>
Community
  • 1
  • 1
Jim C
  • 3,957
  • 25
  • 85
  • 162
  • *"I believe my question provides a good idea what I am trying to do."* - That is up to the reader to judge. Note that you don't actually *ask* a question (except in the title ... sort of). You could also do a lot better with spelling, grammar, punctuation and general readability. (IMO, get rid of the unconvincing waffle about why you think your question is a good question, and focus on *actually making* it a good question.) – Stephen C Jul 30 '16 at 02:44
  • Stephen, if I ask a question in title then I did ask a question. I have read several time here someone starting similar as I started my question and it is the first I saw someone complaining. Where do I tell I have done a good question? I told someone provided an excellent answer to my previous question (complete oposite from what you are saying). About spelling and grammar, unfortunately English is not my mother language and I always try my best to avoid English mistake but I do not know which error you are talking about. Finally, what is really wrong with my question? – Jim C Jul 30 '16 at 03:38
  • Any question that wastes >>the reader's<< time by trying to convince him / her that it is a good question is NOT a good question. Because ... it wasted the reader's time. Is that hard to understand? Really? – Stephen C Jul 30 '16 at 03:42
  • 1
    The desired "JSON" starting with two opening curly braces `{ {` is not valid JSON at all. – Martin Honnen Jul 30 '16 at 08:39
  • Correct, it was a typo. – Jim C Jul 30 '16 at 14:21
  • Stephen, I am very interested to learn what I did wrong in your view but you are not helping. Where did you get the impression that I tried to convinced someone that it was a good question? I stated the question gave a good idea about my intentions. Kindly, compare your critic with Michael one: he added usefull coment when he says it is trivial. Actually, if he points a question here that would answer my issue he could downgrade my question (ps. my concern is not only transform from xml to json). If you look at my second post you see an excellent example of critic, desired outcome missed – Jim C Jul 30 '16 at 14:34

2 Answers2

2

The XSLT you have shown is on the right path, but you are missing a few things

  1. No template handling the c:item itself to wrap the child nodes in { }
  2. No output of commas and line-breaks to separate objects
  3. No handling of the root element c:product to create a child array (so you have valid JSON)

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="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>

When you apply this XSLT to the following XML

<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>

The following is output

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

This doesn't actually match the desired output in your question, but the output you are shown isn't actually valid JSON.

See this answer in action at http://xsltransform.net/ejivdGD

Tim C
  • 70,053
  • 14
  • 74
  • 93
  • Tim C, you answered perfectly my doubt. There is just a small adjustment I want to do in this xsl that wans't orginally asked. Since, in my real world, I figured out that aa will always be two number digit code (e.g. 99) and bbb will always be three number digits (e.g. 999) I understand I can have a valid json file without "aa" and "bbb". How can I do it? I created a new question here with this specific doubt http://stackoverflow.com/questions/38701874/how-transform-from-xml-to-json-with-xsl-and-removing-the-item-record-labels – Jim C Aug 01 '16 at 14:49
1

Getting from

<c:aa name="024" value="123"/>

to

"aa" : {"024":"123"}

is completely trivial: it's just

<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:template>

I can't quite see why you are having problems.

Michael Kay
  • 156,231
  • 11
  • 92
  • 164
  • Michael, thanks for you answer but certainly I missed either part of your answer or some basic idea from xls that you were expecting me to already know. Kindly, note that I tried your suggestion but firstly, I am not getting a valid json and secondly I am "mixing" the items. Please, just copy my input xml and run against your xls suggestion and you will see that I can't distinguish which "aa" or "bbb" belongs to the first item and which one to the last one. I want delete the cod and package attributes during transformation but naturally I don't want to mess up the first item with second – Jim C Aug 01 '16 at 02:42
  • 1
    The fact that you're still spelling XSL as "xls" is a giveaway that you're very new to this language, and it's very difficult to know how to respond to questions from very raw beginners, because we don't know how much you know. It's not possible or appropriate to answer a question with a tutorial, and in my view it's not appropriate to give a complex working solution either, because I think you need to work that out for yourself: the thing about a good SO question is it focuses on one key area where you are stuck, and it's hard to see in your question where your blocker lies. – Michael Kay Aug 01 '16 at 10:03
  • Michael, I am humble about this topic and I am thankfull for your effort to help me. – Jim C Aug 01 '16 at 14:19