novein
novein

Reputation: 53

transform an xml into suitable text

I have an xml, that looks like this

<person>
   <name>
      <name-first>foo</name-first>
      <name-last>bar</name-last>
   </name>
   <age>20</age>
   <city>nowhere</city>
 </person>

I want to convert this into

person:
   {
     name: {
             name-first:'foo', 
             name-last:'bar'  
           }, 
    age:'20',
    city:'nowhere' 
  }

Thanks in advance.

Upvotes: 2

Views: 113

Answers (4)

Dimitre Novatchev
Dimitre Novatchev

Reputation: 243579

Here is a simple transformation -- for a start:

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

 <xsl:param name="pIndents" select="'  '"/>

 <xsl:template match="*[*]">
   <xsl:param name="pcurrentIndents" select="''"/>
     <xsl:value-of select="concat($pcurrentIndents, name(), ':')"/>
     <xsl:value-of select="concat('&#xA;',$pcurrentIndents, '{')"/>
      <xsl:apply-templates>
        <xsl:with-param name="pcurrentIndents" select=
         "concat($pcurrentIndents, $pIndents)"/>
      </xsl:apply-templates>
     <xsl:value-of select="concat('&#xA;',$pcurrentIndents,  '}')"/>
 </xsl:template>

 <xsl:template match="*[not(*)]">
  <xsl:param name="pcurrentIndents" select="''"/>
  <xsl:text>&#xA;</xsl:text>
  <xsl:value-of select="concat($pcurrentIndents, name(), ':')"/>
  <xsl:apply-templates/>
 </xsl:template>
</xsl:stylesheet>

when this transformation is applied on the provided XML document:

<person>
    <name>
        <name-first>foo</name-first>
        <name-last>bar</name-last>
    </name>
    <age>20</age>
    <city>nowhere</city>
</person>

the wanted, correct result is produced:

person:
{  name:
  {
    name-first:foo
    name-last:bar
  }
  age:20
  city:nowhere
}

Explanation:

  1. There are two templates that match elements.

  2. The template matching *[*] matches elements that have elements as children. It produces the name of the currently matched element using the name() function, then the : character, then a NL charactr, the current indentation (number of spaces) and finally the { character. Then templates are applied to the children-nodes of the currently matched element with the $pcurrentIndents parameter passing the current indentation increased with a predifined increment of space characters (as specified in the global parameter $pIndents Finally, on a new line and using the current indentation, the closing curly brace is putput.

  3. The template that matches *[not(*)] (elements that dont have any element as a child) is similar, but simpler. It Outputs the name of the matched element at the current indentation and the : character. Applying templates here invokes th XSLT built-in templates for non-element nodes -- in this case the built-in template matching a text node is selected and it simply copies the text node to the output.

Upvotes: 1

Mads Hansen
Mads Hansen

Reputation: 66781

There are a number of general-purpose XSLT solutions available for converting XML into JSON output.

For instance:

I ran your XML through xml2json-xslt's xml2json.xslt and generated the following JSON output:

{
  "person":
     {
       "name":
         {
           "name-first":"foo",
           "name-last":"bar"
         },
         "age":20,
         "city":"nowhere"
      }
 }

Upvotes: 1

dogbane
dogbane

Reputation: 274828

Here is an example xsl template which should give you some idea of how to convert your xml to the required output:

<xsl:template match="person">
person:
   {
     name: {
             name-first:<xsl:value-of select="name/name-first"/>, 
             name-last:<xsl:value-of select="name/name-last"/>  
           }, 
    age:<xsl:value-of select="age"/>,
    city:<xsl:value-of select="city"/> 
  }
</xsl:template>

Upvotes: 1

Richard Schneider
Richard Schneider

Reputation: 35477

What you want is an XML to JSON converter.

Try this one: http://www.thomasfrank.se/xml_to_json.html

Upvotes: 3

Related Questions