使用XSLT从JSON提取信息并以JSON格式输出格式

时间:2019-06-05 05:25:10

标签: json xml xslt xquery

在一些帮助下,我放置了以下脚本,该脚本将JSON文件作为参数并将其输出为XML。

<?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"
    version="3.0">
    <xsl:param name="json" as="xs:string">
    [
       {
          "ID":"DWL",
          "profiles":[
             {
                "firstName":"Contact",
                "lastName":"Sample",
                "emailAddresses":[
                   {
                      "emailAddress":"inactive@mailinator.com"
                   }
                ]
             }
          ]
       },
       {
          "ID":"DWLK",
          "profiles":[
             {
                "firstName":"Contact",
                "lastName":"Sample",
                "emailAddresses":[
                   {
                      "emailAddress":"sampltest@mailinator.com",
                      "primary":true
                   }
                ]
             }
          ]
       }
    ] 
  </xsl:param>
    <xsl:template match="/" name="xsl:initial-template">
        <xsl:sequence select="json-to-xml($json)"/>
    </xsl:template>
</xsl:stylesheet>

我需要修改脚本以提取ID profiles.FirstNameprofiles.emailAddresses,并添加一个额外的静态字段origin。最终输出应为以下内容:

[  
   {  
      "ID":"DWL",
      "origin":"static",
      "profiles":[  
         {  
            "firstName":"Contact",
            "emailAddresses":[  
               {  
                  "emailAddress":"sample@mailinator.com"
               }
            ]
         }
      ]
   },
   {  
      "ID":"DWLK",
      "origin":"static",
      "profiles":[  
         {  
            "firstName":"Contact",
            "emailAddresses":[  
               {  
                  "emailAddress":"sampltest@mailinator.com",
                  "primary":true
               }
            ]
         }
      ]
   }
]

2 个答案:

答案 0 :(得分:2)

基本上,有两种使用XSLT 3.0处理JSON的方式:您可以将其作为映射和数组来处理,也可以将其转换为XML(然后再次转换为XML)。在XML Prague 2016上的一篇论文(可在http://www.saxonica.com/papers/xmlprague-2016mhk.pdf上),我探索了几个用例,将这两种技术进行了比较,并且我通常发现向XML的转换和向后转换都更加容易,主要原因是XML的模式匹配机制结构比映射和数组的模式匹配要灵活得多(这反过来是因为XML树允许您向上导航以检查上下文,而映射和数组则不允许)。

使用这种方法,您将转换为XML,然后对XML进行标准转换,如下所示:

<xsl:mode name="add-origin" on-no-match="shallow-copy"/>

<xsl:template match="fn:map[*[@key='ID']]" mode="add-origin">
  <xsl:copy>
    <xsl:copy-of select="@*"/>  
    <fn:string key="origin">static</fn:string>
    <xsl:copy-of select="node()"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="/" name="xsl:initial-template">
  <xsl:variable name="converted">  
    <xsl:apply-templates select="json-to-xml($json)" mode="add-origin"/>
  </xsl:variable>
  <xsl:sequence select="xml-to-json($converted)"/>
</xsl:template>

您提到从输入中“提取”一些信息;我不确定我是否理解该要求,但是可以使用查找运算符“?”从parse-json()传递的映射数组表示中很容易地从JSON提取信息。例如,您可以使用$json?*?ID获取所有ID值,或者可以使用$json?*[?ID='JWL']?profiles?1?firstName获取ID为JWL的人的名字。

答案 1 :(得分:0)

使用<xsl:sequence select="json-to-xml($json)"/>进行的第一次转换显示在https://xsltfiddle.liberty-development.net/bnnZWD/5上,并给出了XML

<array xmlns="http://www.w3.org/2005/xpath-functions">
   <map>
      <string key="ID">DWL</string>
      <array key="profiles">
         <map>
            <string key="firstName">Contact</string>
            <string key="lastName">Sample</string>
            <array key="emailAddresses">
               <map>
                  <string key="emailAddress">inactive@mailinator.com</string>
               </map>
            </array>
         </map>
      </array>
   </map>
   <map>
      <string key="ID">DWLK</string>
      <array key="profiles">
         <map>
            <string key="firstName">Contact</string>
            <string key="lastName">Sample</string>
            <array key="emailAddresses">
               <map>
                  <string key="emailAddress">sampltest@mailinator.com</string>
                  <boolean key="primary">true</boolean>
               </map>
            </array>
         </map>
      </array>
   </map>
</array>

如果您将其用作中间结果并通过一些模板(https://xsltfiddle.liberty-development.net/bnnZWD/6)进行推送

  <xsl:template match="/" name="xsl:initial-template">
      <xsl:variable name="json-xml" select="json-to-xml($json)"/>
      <xsl:apply-templates select="$json-xml/node()"/>
  </xsl:template>

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:template match="string[@key = 'ID']">
      <xsl:next-match/>
      <string key="origin">static</string>
  </xsl:template>

  <xsl:template match="string[@key = 'lastName']"/>

要获得的更改:

<array xmlns="http://www.w3.org/2005/xpath-functions">
   <map>
      <string key="ID">DWL</string>
      <string key="origin">static</string>
      <array key="profiles">
         <map>
            <string key="firstName">Contact</string>
            <array key="emailAddresses">
               <map>
                  <string key="emailAddress">inactive@mailinator.com</string>
               </map>
            </array>
         </map>
      </array>
   </map>
   <map>
      <string key="ID">DWLK</string>
      <string key="origin">static</string>
      <array key="profiles">
         <map>
            <string key="firstName">Contact</string>
            <array key="emailAddresses">
               <map>
                  <string key="emailAddress">sampltest@mailinator.com</string>
                  <boolean key="primary">true</boolean>
               </map>
            </array>
         </map>
      </array>
   </map>
</array>

然后您可以使用xml-to-json:(https://xsltfiddle.liberty-development.net/bnnZWD/7)将转换后的XML转换回JSON

  <xsl:output method="text"/>

  <xsl:template match="/" name="xsl:initial-template">
      <xsl:variable name="json-xml" select="json-to-xml($json)"/>
      <xsl:variable name="transformed-json-xml">
            <xsl:apply-templates select="$json-xml/node()"/>
      </xsl:variable>
      <xsl:value-of select="xml-to-json($transformed-json-xml, map { 'indent' : true() })"/>
  </xsl:template>

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:template match="string[@key = 'ID']">
      <xsl:next-match/>
      <string key="origin">static</string>
  </xsl:template>

  <xsl:template match="string[@key = 'lastName']"/>

并使用Saxon 9.8获得输出

  [ 
    { "ID" : "DWL",
      "origin" : "static",
      "profiles" : 
      [ 
        { "firstName" : "Contact",
          "emailAddresses" : 
          [ 
            { "emailAddress" : "inactive@mailinator.com" } ] } ] },

    { "ID" : "DWLK",
      "origin" : "static",
      "profiles" : 
      [ 
        { "firstName" : "Contact",
          "emailAddresses" : 
          [ 
            { "emailAddress" : "sampltest@mailinator.com",
              "primary" : true } ] } ] } ]

清理中间步骤,可以将代码缩短为

  <xsl:output method="text"/>

  <xsl:template match="/" name="xsl:initial-template">
      <xsl:variable name="transformed-json-xml">
            <xsl:apply-templates select="json-to-xml($json)/node()"/>
      </xsl:variable>
      <xsl:value-of select="xml-to-json($transformed-json-xml, map { 'indent' : true() })"/>
  </xsl:template>

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:template match="string[@key = 'ID']">
      <xsl:next-match/>
      <string key="origin">static</string>
  </xsl:template>

  <xsl:template match="string[@key = 'lastName']"/>

https://xsltfiddle.liberty-development.net/bnnZWD/9

当然,除了使用带有JSON字符串内容的参数外,您还可以使用unparsed-text从JSON文件中加载,例如<xsl:param name="json" select="unparsed-text('file.json')"/>