I work on a generic XSL to standardize different nested JSON. My sample JSONs
/soccer2.json
{
"position": "main",
"others": "spiss;sweeper",
"player":
{
"midtbane": [
"offensiv-midtbane",
"defensiv-midtbane"
]
}
}
/soccer1.json
{
"position": "main",
"others": [
{
"wing": "høyreving;venstreving",
"fullback": [
"venstreback",
"høyreback"
]
}
],
"player": [
{
"left": "venstre-midtbane",
"center": "høyre-midtbane",
"right": "sentral-midtbane"
}
]
}
My xsl
const myXsl =
fn.head(xdmp.unquote(
`
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:template match="/">
<sport>
<xsl:if test="exists(position)">
<positionType>
<xsl:copy-of select="position"/>
</positionType>
</xsl:if>
<!-- <xsl:if test="exists(others)">
<otherPosition>
<xsl:copy-of select="others"/>
</otherPosition>
</xsl:if>
-->
<xsl:if test="exists(player)">
<playerPosition>
<xsl:for-each select="player/child::node()">
<xsl:element name="{name()}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:for-each>
</playerPosition>
</xsl:if>
</sport>
</xsl:template>
</xsl:transform>
`));
const doc = cts.doc('/soccer2.json')
xdmp.xsltEval(myXsl, doc)
Unexpected output:
/soccer2.json
<sport>
<positionType>main</positionType>
<otherPosition>spiss;sweeper</otherPosition>
<playerPosition>
<midtbane>["offensiv-midtbane", "defensiv-midtbane"]</midtbane>
</playerPosition>
</sport>
Expected output:
/soccer2.json
<sport>
<positionType>main</positionType>
<otherPosition>spiss;sweeper</otherPosition>
<playerPosition>
<midtbane>offensiv-midtbane</midtbane>
<midtbane>defensiv-midtbane</midtbane>
</playerPosition>
</sport>
Do I expect this work in XSLT? Thanks in advance for any help!
CodePudding user response:
XSLT 3.0 has the ability to process JSON: earlier versions do not. You don't appear to be making use of the XSLT 3.0 capabilities for handling JSON.
(You've tagged it "marklogic" - perhaps there is something in the ML XSLT processor that would make this work; I wouldn't know about that).
I would expect your code simply to fail saying that the input isn't well-formed XML.
CodePudding user response:
The MarkLogic XSLT implementation, you should be looking at:
const implFlattenJToX=
fn.head(xdmp.unquote(
`
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xdmp="http://marklogic.com/xdmp"
xdmp:dialect="1.0-ml" version="2.0">
<xsl:template name="sport">
<xsl:variable name="v_position" select="position"/>
<xsl:variable name="v_player" select="player"/>
<sport>
<xsl:if test="exists(position)">
<positionType>
<xsl:copy-of select="position"/>
</positionType>
</xsl:if>
<xsl:if test="exists($v_player)">
<playerPosition>
<xsl:for-each select="/player">
<xsl:call-template name="flattenJson"/>
</xsl:for-each>
</playerPosition>
</xsl:if>
</sport>
</xsl:template>
<xsl:template name="flattenJson">
<xsl:for-each select="*">
<xsl:choose>
<xsl:when test="array-node()|object-node()">
<xsl:for-each select="./node()">
<xsl:apply-templates select="xdmp:from-json(.)"/>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:element name="{(name(.))}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
<xsl:template match="/">
<xsl:call-template name="sport"/>
</xsl:template>
</xsl:transform>
`));