Last active
July 7, 2017 16:43
-
-
Save tvnpraveen/8e178733cf08192c4c2eb37aa9638ce0 to your computer and use it in GitHub Desktop.
XML to JSON Conversion query
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
xquery version "1.0-ml"; | |
(:~ This library is a simple XML to JSON conversion utility. | |
: ****This library does not support attributes in XML | |
: | |
: | |
:) | |
module namespace xml2json = "http://lib/utils/xml2json"; | |
import module namespace functx = "http://www.functx.com" at "/MarkLogic/functx/functx-1.0-nodoc-2007-01.xqy"; | |
(:~ | |
External variables | |
:) | |
declare variable $booleanElements := map:map(); | |
declare variable $integerElements := map:map(); | |
declare variable $arrayElements := map:map(); | |
(:~ | |
Internal variables | |
:) | |
declare variable $elementMap := map:map(); | |
declare variable $autoArray := fn:false(); | |
(: ######## JSON STRING FORMAT FUNCTIONS : BEGIN :) | |
(:~ | |
This function wraps a given text with double quotes | |
@param val - Input string | |
@return xs:string - Returns string wrapped in quotes | |
:) | |
declare private function xml2json:wrapQuotes($val as xs:string) as xs:string { | |
""""||$val||"""" | |
}; | |
(:~ | |
This function joins JSON key:value strings seperated by comma and wraps them in braces | |
@param vals - Input JSON key:value strings | |
@return xs:string - Returns a JSON object type string | |
:) | |
declare private function xml2json:combineAndWrapInBraces($vals as xs:string*) as xs:string { | |
"{"||fn:string-join($vals,",")||"}" | |
}; | |
(: ######## JSON STRING FORMAT FUNCTIONS : END :) | |
(: ######## DATA FORMAT FUNCTIONS : BEGIN :) | |
(:~ | |
This function checks a given input nodeName against a given set of element maps for boolean or integer | |
and returns the value as is OR wrapped with quotes if there is no match | |
@param nodeName - Node name to match | |
@param text - Node value | |
@return xs:string - Returns the node value depending on the data type | |
:) | |
declare private function xml2json:getTextFromMapping($nodeName as xs:string, $text as xs:string) as xs:string{ | |
let $val := fn:normalize-space($text) | |
return | |
if (map:contains($booleanElements, $nodeName) or map:contains($integerElements, $nodeName)) then | |
$val | |
else (xml2json:wrapQuotes($val)) | |
}; | |
(: ######## DATA FORMAT FUNCTIONS : END :) | |
(: ######## MAIN RECURSIVE FUNCTION : BEGIN :) | |
(:~ | |
This function is the main recursive function which basically evaluates all the given node and all its children nodes in a recursive method | |
@param - node - XML node to be parsed as JSON | |
@return - xs:string - JSON string | |
:) | |
declare private function xml2json:convertXMLToJson($node as node()) as xs:string? { | |
let $ln := fn:local-name($node) | |
return | |
typeswitch($node) | |
case element() return | |
( | |
(: Logic for array element check :) | |
let $arrayElementCheck := | |
if($autoArray) then | |
if ( fn:count($node/../element()[fn:local-name() eq $ln]) gt 1) then fn:true() else fn:false() | |
else( | |
map:contains($arrayElements,$ln) | |
) | |
return | |
if($arrayElementCheck) then | |
( | |
if(fn:not($node/node())) then | |
xml2json:wrapQuotes($ln)||" : []" | |
else( | |
let $parentPosition := fn:generate-id($node/..) | |
let $nodePath := xs:string($parentPosition)||$ln | |
return | |
if(fn:not(map:contains($elementMap, $nodePath))) then | |
( | |
let $_ := map:put($elementMap, $nodePath, $nodePath) | |
return | |
xml2json:wrapQuotes($ln)||" : ["|| | |
fn:string-join( | |
( | |
let $childNodes := $node/../element()[fn:local-name(.) eq $ln] | |
for $childNode at $pos in $childNodes | |
return | |
( | |
if($childNode/node() instance of text()) then | |
xml2json:convertXMLToJson($childNode/text()) | |
else ( | |
xml2json:combineAndWrapInBraces(xml2json:convertXMLToJson($childNode/node())) | |
) | |
) | |
) | |
, | |
"," | |
) | |
||"]" | |
) | |
else() | |
) | |
) | |
else if($node/text()) then | |
xml2json:wrapQuotes($ln)||" : "||xml2json:getTextFromMapping($ln, $node/text()) | |
else if($node/element()) then | |
xml2json:wrapQuotes($ln)||" : "||xml2json:combineAndWrapInBraces(xml2json:convertXMLToJson($node/node())) | |
else if(fn:not($node/node())) then | |
xml2json:wrapQuotes($ln)||" : null" | |
else() | |
) | |
case text() return | |
xml2json:getTextFromMapping(fn:local-name($node/..),$node) | |
default return | |
() | |
}; | |
(: ######## MAIN RECURSIVE FUNCTION : END :) | |
(:~ ######## ACCESS FUNCTIONS WITH NO ADDITIONAL MAP INPUT ########## :) | |
(:~ | |
This function will convert XML document from an URI to JSON. | |
The array elements will be automatically parsed depending on the input | |
@param doc - XML document to be parsed | |
@return xs:string - Returns a JSON string | |
:) | |
declare function xml2json:getJSONFromXMLURI($URI as xs:string){ | |
xml2json:getJSONFromXMLURI($URI, (), (), ()) | |
}; | |
(:~ | |
This function will convert XML document to JSON. | |
The array elements will be automatically parsed depending on the input | |
@param doc - XML document to be parsed | |
@return xs:string - Returns a JSON string | |
:) | |
declare function xml2json:getJSONFromXMLDoc($doc as document-node()) as xs:string { | |
xml2json:getJSONFromXMLDoc($doc, (), (), ()) | |
}; | |
(:~ | |
This function will convert XML node to JSON. | |
The array elements will be automatically parsed depending on the input | |
@param doc - XML document to be parsed | |
@return xs:string - Returns a JSON string | |
:) | |
declare function xml2json:getJSONFromXMLNode($node as node()) as xs:string { | |
xml2json:getJSONFromXMLNode($node, (), (), ()) | |
}; | |
(:~ ######## ACCESS FUNCTIONS WITH ONLY ARRAY ELEMENTS MAP INPUT ########## | |
Example - | |
Sample XML : | |
<test> | |
<firstElement> | |
<firstChildElement> | |
firstChildText | |
</firstChildElement> | |
<secondChildElement> | |
secondChildText1 | |
</secondChildElement> | |
<secondChildElement> | |
secondChildText2 | |
</secondChildElement> | |
</firstElement> | |
<firstElement> | |
<firstChildElement> | |
firstChildText1 | |
</firstChildElement> | |
</firstElement> | |
</test> | |
inputArrayElements : | |
map:map( | |
<map:map xmlns:map="http://marklogic.com/xdmp/map" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema"> | |
<map:entry key="firstElement"> | |
<map:value xsi:type="xs:string">firstElement</map:value> | |
</map:entry> | |
<map:entry key="secondChildElement"> | |
<map:value xsi:type="xs:string">secondChildElement</map:value> | |
</map:entry> | |
</map:map>) | |
JSON Output From above input: | |
{ | |
"test": { | |
"firstElement": [{ | |
"firstChildElement": "firstChildText", | |
"secondChildElement": ["secondChildText1", | |
"secondChildText2"] | |
}, | |
{ | |
"firstChildElement": "firstChildText1" | |
}] | |
} | |
} | |
:) | |
(:~ | |
This function will convert XML document to JSON with an additional input for arrayElements | |
@param doc - XML document to be parsed | |
@param inputArrayElements - This is a Map of array elements to be parsed as JSON arrays. Refer to above example | |
@return xs:string - Returns a JSON string | |
:) | |
declare function xml2json:getJSONFromXMLURI($URI as xs:string, | |
$inputArrayElements as map:map){ | |
xml2json:getJSONFromXMLURI($URI, $inputArrayElements, (), ()) | |
}; | |
(:~ | |
This function will convert XML document to JSON with an additional input for arrayElements | |
@param doc - XML document to be parsed | |
@param inputArrayElements - This is a Map of array elements to be parsed as JSON arrays. Refer to above example | |
@return xs:string - Returns a JSON string | |
:) | |
declare function xml2json:getJSONFromXMLDoc($doc as document-node(), | |
$inputArrayElements as map:map){ | |
xml2json:getJSONFromXMLDoc($doc, $inputArrayElements, (), ()) | |
}; | |
(:~ | |
This function will convert XML document to JSON with an additional input for arrayElements | |
@param doc - XML document to be parsed | |
@param inputArrayElements - This is a Map of array elements to be parsed as JSON arrays. Refer to above example | |
@return xs:string - Returns a JSON string | |
:) | |
declare function xml2json:getJSONFromXMLNode($node as node(), | |
$inputArrayElements as map:map){ | |
xml2json:getJSONFromXMLNode($node, $inputArrayElements, (), ()) | |
}; | |
(:~ ######## ACCESS FUNCTIONS WITH ARRAY ELEMENTS MAP, BOOLEAN ELEMENTS MAP, AND INTEGER ELEMENTS MAP INPUT ########## | |
Example - | |
Sample XML : | |
<test> | |
<firstElement> | |
<firstChildElement> | |
firstChildText | |
</firstChildElement> | |
<firstChildBooleanElement> | |
false | |
</firstChildBooleanElement> | |
<secondChildElement> | |
secondChildText1 | |
</secondChildElement> | |
<secondChildElement> | |
secondChildText2 | |
</secondChildElement> | |
</firstElement> | |
<firstElement> | |
<firstChildElement> | |
firstChildText1 | |
</firstChildElement> | |
<firstChildIntegerElement> | |
false | |
</firstChildIntegerElement> | |
</firstElement> | |
</test> | |
inputArrayElements : | |
map:map( | |
<map:map xmlns:map="http://marklogic.com/xdmp/map" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema"> | |
<map:entry key="firstElement"> | |
<map:value xsi:type="xs:string">firstElement</map:value> | |
</map:entry> | |
<map:entry key="secondChildElement"> | |
<map:value xsi:type="xs:string">secondChildElement</map:value> | |
</map:entry> | |
</map:map>) | |
inputBooleanElements : | |
map:map( | |
<map:map xmlns:map="http://marklogic.com/xdmp/map" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema"> | |
<map:entry key="firstChildBooleanElement"> | |
<map:value xsi:type="xs:string">firstElement</map:value> | |
</map:entry> | |
</map:map>) | |
inputIntegerElements : | |
map:map( | |
<map:map xmlns:map="http://marklogic.com/xdmp/map" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema"> | |
<map:entry key="firstChildIntegerElement"> | |
<map:value xsi:type="xs:string">firstElement</map:value> | |
</map:entry> | |
</map:map>) | |
JSON Output From above input: | |
{ | |
"test": { | |
"firstElement": [{ | |
"firstChildElement": "firstChildText", | |
"secondChildElement": ["secondChildText1", | |
"secondChildText2"] | |
}, | |
{ | |
"firstChildElement": "firstChildText1" | |
}] | |
} | |
} | |
:) | |
(:~ | |
This function will convert XML document from an URI to JSON with an additional input for arrayElements, booleanElements, integerElements | |
@param doc - XML document to be parsed | |
@param inputArrayElements - This is a Map of array elements to be parsed as JSON arrays | |
@param inputBooleanElements - This is a Map of boolean type elements to be parsed as JSON boolean type | |
@param inputIntegerElements - This is a Map of integer elements to be parsed as JSON boolean type | |
@return xs:string - Returns a JSON string | |
:) | |
declare function xml2json:getJSONFromXMLURI($URI as xs:string, | |
$inputArrayElements as map:map?, | |
$inputBooleanElements as map:map?, | |
$inputIntegerElements as map:map?) as xs:string{ | |
xml2json:getJSONFromXMLDoc(fn:doc($URI), $inputArrayElements, $inputBooleanElements, $inputIntegerElements) | |
}; | |
(:~ | |
This function will convert XML document to JSON with an additional input for arrayElements, booleanElements, integerElements | |
@param doc - XML document to be parsed | |
@param inputArrayElements - This is a Map of array elements to be parsed as JSON arrays | |
@param inputBooleanElements - This is a Map of boolean type elements to be parsed as JSON boolean type | |
@param inputIntegerElements - This is a Map of integer elements to be parsed as JSON boolean type | |
@return xs:string - Returns a JSON string | |
:) | |
declare function xml2json:getJSONFromXMLDoc($doc as document-node(), | |
$inputArrayElements as map:map?, | |
$inputBooleanElements as map:map?, | |
$inputIntegerElements as map:map?) as xs:string{ | |
xml2json:getJSONFromXMLNode($doc/node(), $inputArrayElements, $inputBooleanElements, $inputIntegerElements) | |
}; | |
(:~ | |
This function will convert XML node to JSON with an additional input for arrayElements, booleanElements, integerElements | |
@param doc - XML document to be parsed | |
@param inputArrayElements - This is a Map of array elements to be parsed as JSON arrays | |
@param inputBooleanElements - This is a Map of boolean type elements to be parsed as JSON boolean type | |
@param inputIntegerElements - This is a Map of integer elements to be parsed as JSON boolean type | |
@return xs:string - Returns a JSON string | |
:) | |
declare function xml2json:getJSONFromXMLNode($node as node(), | |
$inputArrayElements as map:map?, | |
$inputBooleanElements as map:map?, | |
$inputIntegerElements as map:map?) as xs:string{ | |
let $_ := | |
( | |
if(map:count($inputArrayElements) ge 1) then | |
xdmp:set($arrayElements, $inputArrayElements) | |
else (xdmp:set($autoArray, fn:true())) | |
, | |
if(map:count($inputBooleanElements) ge 1) then | |
xdmp:set($booleanElements, $inputBooleanElements) | |
else() | |
, | |
if(map:count($inputIntegerElements) ge 1) then | |
xdmp:set($integerElements, $inputIntegerElements) | |
else() | |
) | |
return | |
xml2json:combineAndWrapInBraces(xml2json:convertXMLToJson($node)) | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment