首页 > 解决方案 > xml到json中单个和多个LineItem的方括号

问题描述

如何为单个或多个“详细信息”行项获取方括号或数组。需要获得方括号或数组 [ 即使对于单行“详细信息”也是如此。我们有超过 1 行“详细信息”。要求是填充 [ 甚至从单行“详细信息”。

单行“详细信息”的 xmlFile:

<root>
    <FirstName>Alex</FirstName>
    <LastName>Fin</LastName>
    <Details>
        <Id_Number>111</Id_Number>
        <Location>NC</Location>
        <Contact>
             <PhoneNumber>+1 323</PhoneNumber>
         </Contact>
    </Details>
</root>

预期的Json文件:

     {
    "FirstName": "Alex",
    "LastName": "Fin",
    "Details": [
      {
        "Id_Number": 111,
        "Location": "NC",
        "Contact": {
          "PhoneNumber": "+1 323"
        }
      }
    ]
 }

带有多行'详细信息的xml文件:

<root>
        <FirstName>Alex</FirstName>
        <LastName>Fin</LastName>
        <Details>
            <Id_Number>111</Id_Number>
            <Location>NC</Location>
            <Contact>
                 <PhoneNumber>+1 323</PhoneNumber>
             </Contact>
        </Details>
        <Details>
            <Id_Number>222</Id_Number>
            <Location>TX</Location>
            <Contact>
                 <PhoneNumber>+1 323</PhoneNumber>
             </Contact>
        </Details>
        <Address>
            <Locality>Urban</Locality>
            <Distance>
               <Miles>2</Miles>
            </Distance>
            <Commute>Yes</Commute>
         </Address>
         <Address>
            <Locality>Rular</Locality>
            <Distance>
               <Miles>1</Miles>
            </Distance>
            <Commute>Yes</Commute>
         </Address>
    </root>

多个 LineItems'Details' 的预期 Jsonfile

    {
    "FirstName": "Alex",
    "LastName": "Fin",
    "Details": [
      {
        "Id_Number": 111,
        "Location": "NC",
        "Contact": {
          "PhoneNumber": "+1 323"
        }
      },
      {
        "Id_Number": 222,
        "Location": "TX",
        "Contact": {
          "PhoneNumber": "+1 323"
        }
      }
    ],
    "Address": [
      [
          {
        "Locality": "Urban",
        "Distance": {
          "Miles": 2
        },
        "Commute": "Yes"
      }
      ],
      [
          {
        "Locality": "Rular",
        "Distance": {
          "Miles": 1
        },
        "Commute": "Yes"
      }
      ]
    ]
  }

xslt代码:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    xmlns="http://www.w3.org/2005/xpath-functions"
    expand-text="yes"
    version="3.0">

  <xsl:output method="text"/>

  <xsl:template match="/">
      <xsl:variable name="json-xml">
          <xsl:apply-templates/>
      </xsl:variable>
      <xsl:value-of select="xml-to-json($json-xml, map { 'indent' : true() })"/>
  </xsl:template>
  
  <xsl:template match="*[not(*)]">
    <string key="{local-name()}">{.}</string>
  </xsl:template>
  
  <xsl:template match="*[(*) and . castable as xs:double]">
    <number key="{local-name()}">{.}</number>
  </xsl:template>
  
  <xsl:template match="*[*]">
    <xsl:param name="key" as="xs:boolean" select="false()"/>
    <map>
      <xsl:if test="$key">
        <xsl:attribute name="key" select="local-name()"/>
      </xsl:if>
      <xsl:for-each-group select="*" group-by="node-name()">
          <xsl:choose>
              <xsl:when test="current-group()[2] or self::Details or self::Contact">
                  <array key="{local-name()}">
                    <xsl:choose>
                      <xsl:when test="self::Address">
                        <array>
                          <xsl:apply-templates select="current-group()">
                            <xsl:with-param name="key" select="false()"/>
                          </xsl:apply-templates>                        
                        </array>
                      </xsl:when>
                      <xsl:otherwise>
                        <xsl:apply-templates select="current-group()">
                          <xsl:with-param name="key" select="false()"/>
                        </xsl:apply-templates>
                      </xsl:otherwise>                      
                    </xsl:choose>
                  </array>
              </xsl:when>
              <xsl:otherwise>
                  <xsl:apply-templates select="current-group()">
                    <xsl:with-param name="key" select="true()"/>
                  </xsl:apply-templates>
              </xsl:otherwise>
          </xsl:choose>
      </xsl:for-each-group>
    </map>
  </xsl:template>

</xsl:stylesheet>

标签: jsonxsltxslt-2.0xslt-groupingxslt-3.0

解决方案


当一组同名节点包含两个或多个项目时,代码将生成一个数组:

<xsl:when test="current-group()[2]">
    <array key="{local-name()}">
        <xsl:apply-templates select="current-group()"/>
    </array>
</xsl:when>

所以最简单的解决方法是在元素名称为“详细信息”时使用相同的逻辑:

<xsl:when test="current-group()[2] or self::Details">

或者更好的设计可能是使其成为数据驱动的;有一个全局变量,其中包含要强制数组输出的元素名称列表,并测试该元素在此列表中的成员资格。


推荐阅读