微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在xml到json转换中排序和分组

如何解决在xml到json转换中排序和分组

我正在尝试根据“地址”中的“itemLotNo”对订单项进行排序和分组。当 Address 中的 lineitems 相同时,它们应该在方括号或 Array Address[[{...},{...}],[{...}],[{...}]] 之间形成.

数据应该保持不变,即行项目没有变化,只需对相同的“itemLotNo”进行排序和分组。

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>
        <itemLotNo>19949-2018-0001-45116-Dot1</itemLotNo>
        <Locality>Urban</Locality>
        <Type>Mobile</Type>
    </Address>
    <Address>
        <itemLotNo>19950-2018-0001-45116-Dot1</itemLotNo>
        <Locality>Rural</Locality>
        <Type>Landline</Type>
    </Address>
    <Address>
        <itemLotNo>19949-2018-0001-45116-Dot1</itemLotNo>
        <Locality>Rural</Locality>
        <Type>Landline</Type>
    </Address>
    <Address>
        <itemLotNo>19958-2018-0001-45116-Dot1</itemLotNo>
        <Locality>Rural</Locality>
        <Type>Landline</Type>
    </Address>
</root>

预期的Json文件

{
  "FirstName": "Alex","LastName": "Fin","Details": [
    [
      {
        "Id_Number": "111","Location": "NC","Contact": {
          "PhoneNumber": "+1 323"
        }
      },{
        "Id_Number": "222","Location": "TX","Contact": {
          "PhoneNumber": "+1 323"
        }
      }
    ]
  ],"Address": [
    [
      {
        "itemLotNo": "19949-2018-0001-45116-Dot1","Locality": "Urban","Type": "Mobile"
      },{
        "itemLotNo": "19949-2018-0001-45116-Dot1","Locality": "Rural","Type": "Landline"
      }
    ],[
      {
        "itemLotNo": "19950-2018-0001-45116-Dot1",[
      {
        "itemLotNo": "19958-2018-0001-45116-Dot1","Type": "Landline"
      }
    ]
  ]
}

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::Address">
                  <array key="{local-name()}">
                    <xsl:choose>
                      <xsl:when test="self::Details">
                        <array>
                          <xsl:apply-templates select="current-group()">
                            <xsl:with-param name="key" select="false()"/>
                          </xsl:apply-templates>                        
                        </array>
                      </xsl:when>
<xsl:when test="self::Address">
                        <xsl:iterate select="current-group()">
<array>
                          <xsl:apply-templates select="self::Address">

                          </xsl:apply-templates>                        
                        </array>
                        </xsl:iterate>
                      </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>

解决方法

Address 的特殊处理似乎是您想要的

  <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::Address">
                  <array key="{local-name()}">
                    <xsl:choose>
                      <xsl:when test="self::Details">
                        <array>
                          <xsl:apply-templates select="current-group()">
                            <xsl:with-param name="key" select="false()"/>
                          </xsl:apply-templates>                        
                        </array>
                      </xsl:when>
                      <xsl:when test="self::Address">
                        <xsl:for-each-group select="current-group()" group-by="itemLotNo">
                          <array>
                            <xsl:apply-templates select="current-group()">
                              <xsl:with-param name="key" select="false()"/>
                            </xsl:apply-templates>
                          </array>
                        </xsl:for-each-group>
                      </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: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::Address">
            <array key="{local-name()}">
              <xsl:choose>
                <xsl:when test="self::Details">
                    <xsl:apply-templates select="current-group()">
                      <xsl:with-param name="key" select="false()"/>
                    </xsl:apply-templates>                        
                </xsl:when>
                <xsl:when test="self::Address">
                  <xsl:iterate select="current-group()">
                    <xsl:apply-templates select="self::Address"/>
                  </xsl:iterate>
                </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>

你会得到这个json:

{
  "FirstName": "Alex","LastName": "Fin","Details": [
    {
      "Id_Number": "111","Location": "NC","Contact": {"PhoneNumber": "+1 323"}
    },{
      "Id_Number": "222","Location": "TX","Contact": {"PhoneNumber": "+1 323"}
    }
  ],"Address": [
    {
      "itemLotNo": "19949-2018-0001-45116-Dot1","Locality": "Urban","Type": "Mobile"
    },{
      "itemLotNo": "19950-2018-0001-45116-Dot1","Locality": "Rural","Type": "Landline"
    },{
      "itemLotNo": "19949-2018-0001-45116-Dot1",{
      "itemLotNo": "19958-2018-0001-45116-Dot1","Type": "Landline"
    }
  ]
}

这与您的 ExpectedJsonFile 不同,因为它没有用于 Address 和 Details 的嵌套数组,但也许它甚至更好。 See json question about array of objects.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。