Используйте XSLT для извлечения информации из JSON и вывода в формате JSON - PullRequest
0 голосов
/ 05 июня 2019

С некоторой помощью я создал следующий скрипт, который принимает файл 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>

Мне нужно изменить скрипт таким образом, чтобы извлечь идентификатор, profiles.FirstName и profiles.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 ]

2 голосов
/ 05 июня 2019

Существует два основных способа манипулирования JSON с использованием XSLT 3.0: вы можете обрабатывать его как карты и массивы или преобразовывать его в 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>

Вы упоминаете "извлечение" некоторой информации из входных данных; Я не уверен, что понимаю это требование, но извлечение информации из JSON может быть достаточно легко выполнено из представления maps-and-arrays, предоставляемого parse-json (), с использованием оператора поиска «?». Например, вы можете получить все значения идентификатора, используя $json?*?ID, или вы можете получить имя человека с идентификатором JWL, используя $json?*[?ID='JWL']?profiles?1?firstName.

0 голосов
/ 05 июня 2019

Первое преобразование с <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 обратно в JSON, используя xml-to-json: (https://xsltfiddle.liberty -development.net / bnnZWD / 7 )

  <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']"/>

и получить с саксонской 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')"/>.

...