Reputation: 11
I try to convert some xml files (from Freeplane app) to json with xsl syntax ; the result to reach looks like that:
[
{"title": "Animalia", "children": [
{"title": "Chordate", "children": [
{"title": "Mammal", "children": [
{"title": "Primate", "children": [
{"title": "Primate"},
{"title": "Carnivora"}
]},
{"title": "Carnivora", "children": [
{"title": "Felidae"}
]}
]}
]},
{"title": "Arthropoda", "children": [
{"title": "Insect", "children": [
{"title": "Diptera"}
]}
]}
]}
]
Here is my xsl file :
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" indent="no"/>
<xsl:param name="indent-increment" select="' '" />
<xsl:template match="map">
<!-- Ignores root 'node' -->
<xsl:apply-templates select="node/node"/>
</xsl:template>
<xsl:template match="node">
<xsl:param name="indent" select="'
'"/>
<xsl:variable name="indent0" select="$indent" />
<xsl:variable name="indent1" select="concat($indent, $indent-increment)" />
<xsl:if test="position() > 1">, </xsl:if>
<xsl:text>[</xsl:text>
<xsl:value-of select="$indent1"/>
<xsl:text>{"title": "</xsl:text>
<!-- Need to replace " with \" in @TEXT strings -->
<xsl:value-of disable-output-escaping='yes' select="@TEXT"/>
<xsl:text>"</xsl:text>
<!-- Recursion
<xsl:if test="@LINK">
<xsl:text>,</xsl:text>
<xsl:value-of select="$indent1"/>
<xsl:text>url: "</xsl:text>
<xsl:value-of disable-output-escaping='yes' select="@LINK"/>
<xsl:text>"</xsl:text>
</xsl:if>
-->
<xsl:if test="node">
<xsl:text>,</xsl:text>
<xsl:value-of select="$indent1"/>
<xsl:text>"children": </xsl:text>
<!-- Recursion -->
<xsl:apply-templates select="node">
<xsl:with-param name="indent" select="$indent1"/>
</xsl:apply-templates>
<xsl:text>}</xsl:text>
</xsl:if>
<xsl:if test="not(node)">
<xsl:text>}</xsl:text>
</xsl:if>
<xsl:value-of select="$indent"/>
<xsl:text>]</xsl:text>
</xsl:template>
</xsl:stylesheet>
I've tried a lot of combinations in xsl file but I didn't succeed in putting the right syntax to have a clean json at the end. And my json file gives me this (wrong) output :
[
{"title": "Animalia",
"children": [
{"title": "Chordate",
"children": [
{"title": "Mammal",
"children": [
{"title": "Primate",
"children": [
{"title": "Carnivora",
"children": [
{"title": "Felidae"}
]}
]}
]}
]}
], [
{"title": "Arthropoda",
"children": [
{"title": "Insect",
"children": [
{"title": "Diptera"}
]}
]}
]}
]
I know my xsl file is wrong but at this point, I can't find the right solution, so if someone have any idea to how make a well made xsl file to convert into the json I want, I would be very pleased... Thanks
Here is the xml file generated by the Freemind app.:
<map version="1.0.1">
<!-- To view this file, download free mind mapping software FreeMind from http://freemind.sourceforge.net -->
<node CREATED="1484301934011" ID="ID_389012734" MODIFIED="1484301940301" TEXT="test">
<node CREATED="1484301961212" MODIFIED="1484301961212" POSITION="right" TEXT="Animalia">
<node CREATED="1484301961212" MODIFIED="1484301961212" TEXT="Chordate">
<node CREATED="1484301961213" MODIFIED="1484301961213" TEXT="Mammal">
<node CREATED="1484301961214" MODIFIED="1484301961214" TEXT="Primate">
<node CREATED="1484301961214" MODIFIED="1484301961214" TEXT="Carnivora">
<node CREATED="1484301961215" MODIFIED="1484301961215" TEXT="Felidae"/>
</node>
</node>
</node>
</node>
<node CREATED="1484301961216" MODIFIED="1484301961216" TEXT="Arthropoda">
<node CREATED="1484301961216" MODIFIED="1484301961216" TEXT="Insect">
<node CREATED="1484301961217" MODIFIED="1484301961217" TEXT="Diptera"/>
</node>
</node>
</node>
</node>
</map>
Upvotes: 0
Views: 305
Reputation: 5983
Have a look at xsltjson, it probably does exactly what you want as is, but if not you may be able to tweak it to get the output your after
UPDATE :
Given your XML, you are transforming the data and converting it to json. I suggest you treat these to operations separately, convert the XML to a format that suites then convert it to json. I would recommend using an existing library to do the XML to JSON conversion as its fiddly and a home made solution is likely to be buggy.
I suggest you transform your XML to something like
<?xml version="1.0" encoding="UTF-8"?>
<!-- Created with Liquid Studio 2017 - Developer Bundle Edition (Trial) 15.0.0.7084 (https://www.liquid-technologies.com) -->
<children>
<title>test</title>
<children xmlns:json="http://json.org/" json:force-array="true">
<title>Animalia</title>
<children json:force-array="true">
<title>Chordate</title>
<children json:force-array="true">
<title>Mammal</title>
<children json:force-array="true">
<title>Primate</title>
<children json:force-array="true">
<title>Carnivora</title>
<children json:force-array="true">
<title>Felidae</title>
</children>
</children>
</children>
</children>
</children>
<children json:force-array="true">
<title>Arthropoda</title>
<children json:force-array="true">
<title>Insect</title>
<children json:force-array="true">
<title>Diptera</title>
</children>
</children>
</children>
</children>
</children>
then use xsltjson to transform it to json
{
"": {
"children": {
"title": "test",
"children": [
{
"title": "Animalia",
"children": [
{
"title": "Chordate",
"children": [
{
"title": "Mammal",
"children": [
{
"title": "Primate",
"children": [
{
"title": "Carnivora",
"children": [
{
"title": "Felidae"
}
]
}
]
}
]
}
]
},
{
"title": "Arthropoda",
"children": [
{
"title": "Insect",
"children": [
{
"title": "Diptera"
}
]
}
]
}
]
}
]
}
}
}
Something like this should do it
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:json="http://json.org/"
exclude-result-prefixes="xs xsl json">
<xsl:include href="xml-to-json.xsl"></xsl:include>
<xsl:template match="/">
<xsl:variable name="myXml">
<children>
<xsl:apply-templates select="map/*"></xsl:apply-templates>
</children>
</xsl:variable>
<xsl:value-of select="json:generate($myXml)"/>
</xsl:template>
<xsl:template match="node">
<title>
<xsl:value-of select="@TEXT"></xsl:value-of>
</title>
<xsl:for-each select="node">
<children json:force-array="true" xmlns:json="http://json.org/">
<xsl:apply-templates select="."></xsl:apply-templates>
</children>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1