xslt 标准化嵌套 JSON
xslt standardize nested JSON
我使用通用 XSL 来标准化不同的嵌套 JSON。
我的样本 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"
}
]
}
我的 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)
意外输出:
/soccer2.json
<sport>
<positionType>main</positionType>
<otherPosition>spiss;sweeper</otherPosition>
<playerPosition>
<midtbane>["offensiv-midtbane", "defensiv-midtbane"]</midtbane>
</playerPosition>
</sport>
预期输出:
/soccer2.json
<sport>
<positionType>main</positionType>
<otherPosition>spiss;sweeper</otherPosition>
<playerPosition>
<midtbane>offensiv-midtbane</midtbane>
<midtbane>defensiv-midtbane</midtbane>
</playerPosition>
</sport>
我希望这项工作在 XSLT 中有效吗?
XSLT 3.0 有能力处理 JSON:早期版本没有。您似乎没有使用 XSLT 3.0 功能来处理 JSON.
(您已将它标记为“marklogic”——也许 ML XSLT 处理器中有一些东西可以使它工作;我不知道)。
我希望您的代码只是失败,说输入格式不正确 XML。
MarkLogic XSLT 实现,您应该查看:
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" exclude-result-prefixes="xdmp" version="2.0">
<xsl:template name="sport">
<xsl:variable name="v_position" select="position"/>
<xsl:variable name="v_others" select="others"/>
<xsl:variable name="v_player" select="player"/>
<sport>
<xsl:if test="exists(position)">
<positionType>
<xsl:copy-of select="position"/>
</positionType>
</xsl:if>
<xsl:choose>
<xsl:when test="exists($v_others/node())">
<otherPosition>
<xsl:for-each select="$v_others">
<xsl:call-template name="flattenJson"/>
</xsl:for-each>
</otherPosition>
</xsl:when>
<xsl:otherwise>
<xsl:if test="exists($v_others)">
<xsl:apply-templates select="$v_others" mode="flatNode">
<xsl:with-param name="eName" select="'otherPosition'"/>
</xsl:apply-templates>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
<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="*" mode="flatNode">
<xsl:param name="eName"/>
<xsl:element name="{$eName}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
<xsl:template match="/">
<xsl:call-template name="sport"/>
</xsl:template>
</xsl:transform>
`));
Output:
<sport>
<positionType>main</positionType>
<otherPosition>
<wing>høyreving;venstreving</wing>
<fullback>venstreback</fullback>
<fullback>høyreback</fullback>
</otherPosition>
<playerPosition>
<left>venstre-midtbane</left>
<center>høyre-midtbane</center>
<right>sentral-midtbane</right>
</playerPosition>
</sport>
<sport>
<positionType>main</positionType>
<otherPosition>spiss;sweeper</otherPosition>
<playerPosition>
<midtbane>offensiv-midtbane</midtbane>
<midtbane>defensiv-midtbane</midtbane>
</playerPosition>
</sport>
Side note: 1) MarkLogic built-in function json:transform-from-json
, which can be efficiently implemented in standalone XQuery | SJS API or interposed as XSLT import-module
, is another helper to navigate between XML and JSON. 2) flatNode
can be called into flattenJson
.
In this chain, I try to keep the XSL dialect as close to yours as possible.
In reality, I just need slight XPath adjustments without touching the base templates flattenJson
and flatNode
to harmonise complex JSON.
我使用通用 XSL 来标准化不同的嵌套 JSON。 我的样本 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"
}
]
}
我的 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)
意外输出:
/soccer2.json
<sport>
<positionType>main</positionType>
<otherPosition>spiss;sweeper</otherPosition>
<playerPosition>
<midtbane>["offensiv-midtbane", "defensiv-midtbane"]</midtbane>
</playerPosition>
</sport>
预期输出:
/soccer2.json
<sport>
<positionType>main</positionType>
<otherPosition>spiss;sweeper</otherPosition>
<playerPosition>
<midtbane>offensiv-midtbane</midtbane>
<midtbane>defensiv-midtbane</midtbane>
</playerPosition>
</sport>
我希望这项工作在 XSLT 中有效吗?
XSLT 3.0 有能力处理 JSON:早期版本没有。您似乎没有使用 XSLT 3.0 功能来处理 JSON.
(您已将它标记为“marklogic”——也许 ML XSLT 处理器中有一些东西可以使它工作;我不知道)。
我希望您的代码只是失败,说输入格式不正确 XML。
MarkLogic XSLT 实现,您应该查看:
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" exclude-result-prefixes="xdmp" version="2.0">
<xsl:template name="sport">
<xsl:variable name="v_position" select="position"/>
<xsl:variable name="v_others" select="others"/>
<xsl:variable name="v_player" select="player"/>
<sport>
<xsl:if test="exists(position)">
<positionType>
<xsl:copy-of select="position"/>
</positionType>
</xsl:if>
<xsl:choose>
<xsl:when test="exists($v_others/node())">
<otherPosition>
<xsl:for-each select="$v_others">
<xsl:call-template name="flattenJson"/>
</xsl:for-each>
</otherPosition>
</xsl:when>
<xsl:otherwise>
<xsl:if test="exists($v_others)">
<xsl:apply-templates select="$v_others" mode="flatNode">
<xsl:with-param name="eName" select="'otherPosition'"/>
</xsl:apply-templates>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
<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="*" mode="flatNode">
<xsl:param name="eName"/>
<xsl:element name="{$eName}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
<xsl:template match="/">
<xsl:call-template name="sport"/>
</xsl:template>
</xsl:transform>
`));
Output:
<sport>
<positionType>main</positionType>
<otherPosition>
<wing>høyreving;venstreving</wing>
<fullback>venstreback</fullback>
<fullback>høyreback</fullback>
</otherPosition>
<playerPosition>
<left>venstre-midtbane</left>
<center>høyre-midtbane</center>
<right>sentral-midtbane</right>
</playerPosition>
</sport>
<sport>
<positionType>main</positionType>
<otherPosition>spiss;sweeper</otherPosition>
<playerPosition>
<midtbane>offensiv-midtbane</midtbane>
<midtbane>defensiv-midtbane</midtbane>
</playerPosition>
</sport>
Side note: 1) MarkLogic built-in function
json:transform-from-json
, which can be efficiently implemented in standalone XQuery | SJS API or interposed as XSLTimport-module
, is another helper to navigate between XML and JSON. 2)flatNode
can be called intoflattenJson
. In this chain, I try to keep the XSL dialect as close to yours as possible.
In reality, I just need slight XPath adjustments without touching the base templates
flattenJson
andflatNode
to harmonise complex JSON.