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.