I need to transform der memory node to JSON. Expected output:
{
"citations": [
{
"cited": "classes",
"procceding": [
"applied",
"considered",
"followed"
]
},
{
"cited": "toCase",
"procceding": [
"Ty Corp Ltd v Nu Inc",
"PY Arbitrage v Bank of WN"
]
}
]
}
My XQuery:
let $nodes :=
<cases>
<citations>
<classes>
<text>applied</text>
<text>considered</text>
<text>followed</text>
</classes>
<toCase>
<text>Ty Corp Ltd v Nu Inc</text>
<text>PY Arbitrage v Bank of WN</text>
</toCase>
</citations>
</cases>
return
let $map := map:map()
let $p :=
for $node in $nodes/citations/node()
let $nodeName := local-name($node)
let $c :=
map:put($map, "citations", map:new(map:entry('cited', map:new(map:entry($nodeName, (for $value in $node/node() return $value/fn:string(.)) ))) ) )
return $c
return xdmp:to-json($map)
$nodes
is wrongly transformed:
{"citations": {"cited": {"toCase": ["Ty Corp Ltd v Nu Inc", "PY Arbitrage v Bank of WN"]}}
How can I get the expected JSON?
--) You can use json:object() to scaffold in-memory JSON model ( equivalent of XML schema ) and preserve the Object order. I refactor and streamline one of my xml-to-json modules as below. It should fulfill your needs.
declare function local:marshal-json(
$master-node as node()
) as item()
{
let $master-object := json:object()
let $_ :=
for $child-node in $master-node/node()
let $child-name := local-name($child-node)
return
map:put($master-object, $child-name,
for $floor in $child-node/node() return local:floor-object($floor)
)
return $master-object
};
declare function local:floor-object(
$child-node as node()
) as item()
{
let $floor-object := json:object()
let $_ := map:put($floor-object, "cited", local-name($child-node))
let $floor-values := json:array()
let $_ :=
for $gc in $child-node/node()
return json:array-push($floor-values, $gc/fn:string(.))
let $_ := map:put($floor-object, "procceding", $floor-values)
return
$floor-object
};
let $nodes :=
<cases>
<citations>
<classes>
<text>applied</text>
<text>considered</text>
<text>followed</text>
</classes>
<toCase>
<text>Ty Corp Ltd v Nu Inc</text>
<text>PY Arbitrage v Bank of WN</text>
</toCase>
</citations>
</cases>
return
local:marshal-json($nodes)
--) I am not in a position to disapprove over your design. But I approve the spirit. You should be able to transform the XML to JSON (with parameters not hardcoded JSON names) using similar logic.
Example: Transform
<investment>
<entity>
<name>XYZ</name>
</entity>
<bogus>encrypted</bogus>
<property>
<Canadian>
<propertyType>eligible dividend of CPC</propertyType>
<notionalAmount>10000</notionalAmount>
</Canadian>
<foreign>
<propertyType>dividend of trust</propertyType>
<notionalAmount>7000</notionalAmount>
<foreignWithholding>660</foreignWithholding>
</foreign>
</property>
<capital>
<portfolio>
<name>HF25</name>
<inadequateConsiderationFMV>10000</inadequateConsiderationFMV>
<transferredAmount>15000</transferredAmount>
<gainLossOnDisposition>11000</gainLossOnDisposition>
</portfolio>
<portfolio>
<name>UL1</name>
<superficialLoss>17000</superficialLoss>
<reacquired>5000</reacquired>
<gainLossOnDisposition>-2000</gainLossOnDisposition>
</portfolio>
<security-CUSIP1>
<gainLossOnDisposition>-3600</gainLossOnDisposition>
</security-CUSIP1>
</capital>
</investment>
to JSON:
{
"entity": {
"name": "XYZ"
},
"bogus": null,
"property": {
"Canadian": {
"propertyType": "eligible dividend of CPC",
"notionalAmount": 10000
},
"foreign": {
"propertyType": "dividend of trust",
"notionalAmount": 7000,
"foreignWithholding": 660
}
},
"capital": {
"portfolio": [
{
"name": "HF25",
"inadequateConsiderationFMV": 10000,
"transferredAmount": 15000,
"gainLossOnDisposition": 11000
},
{
"name": "UL1",
"superficialLoss": 17000,
"reacquired": 5000,
"gainLossOnDisposition": -2000
}
],
"security-CUSIP1": {
"gainLossOnDisposition": -3600
}
}
}
I use low-level APIs with more leverage: It transforms XML string/text to JSON string
or number
upon instructions; It conforms to the customised JSON model, object and array structure; It observes XML/JSON naming convention in financial domain.
--) That said, this programming model is memory-intensive. If XSLT3 parses and transforms JSON in streaming model in Java, it could be more memory-efficient. I never use XSLT3 JSON parser as now and can’t comment on its efficacy.