使用 XSLT 3.0 进行转换 XML

Using XSLT 3.0 to transform XML

我想使用 XSLT 将一些 XML 转换为 JSON。 XML 如下所示:

<?xml version="1.0" ?>
<CoronaInfections>
    <Countries>
        <item>
            <Country>Afghanistan</Country>
            <CountryCode>AF</CountryCode>
            <Slug>afghanistan</Slug>
            <NewConfirmed>542</NewConfirmed>
            <TotalConfirmed>21459</TotalConfirmed>
            <NewDeaths>15</NewDeaths>
            <TotalDeaths>384</TotalDeaths>
            <NewRecovered>480</NewRecovered>
            <TotalRecovered>2651</TotalRecovered>
            <Date>2020-06-10T10:06:56Z</Date>
            <Lat>33.0000</Lat>
            <Lng>65.0000</Lng>
        </item>
        <item>
            <Country>Albania</Country>
            <CountryCode>AL</CountryCode>
            <Slug>albania</Slug>
            <NewConfirmed>36</NewConfirmed>
            <TotalConfirmed>1299</TotalConfirmed>
            <NewDeaths>0</NewDeaths>
            <TotalDeaths>34</TotalDeaths>
            <NewRecovered>15</NewRecovered>
            <TotalRecovered>960</TotalRecovered>
            <Date>2020-06-10T10:06:56Z</Date>
            <Lat>41.0000</Lat>
            <Lng>20.0000</Lng>
        </item>
        <item>
            <Country>Algeria</Country>
            <CountryCode>DZ</CountryCode>
            <Slug>algeria</Slug>
            <NewConfirmed>117</NewConfirmed>
            <TotalConfirmed>10382</TotalConfirmed>
            <NewDeaths>9</NewDeaths>
            <TotalDeaths>724</TotalDeaths>
            <NewRecovered>152</NewRecovered>
            <TotalRecovered>6951</TotalRecovered>
            <Date>2020-06-10T10:06:56Z</Date>
            <Lat>28.0000</Lat>
            <Lng>3.0000</Lng>
        </item>
   </Countries>
</CoronaInfections>

我希望 JSON 如下所示:

{ "type": "FeatureCollection",
    "features": [
        {
            "type": "Feature",
                "properties": {
                "radius": 1.0841103742476927, 
                "id": "AF", 
                "countryName": "Afghanistan" 
            },
        },
        {
            "type": "Feature",
            "geometry": {
                "type": "Point",
                "coordinates": [33.0000, 65.0000]
                },
        },
        {
            "type": "Feature",
                "properties": {
                "radius": 0.06562558255966042, 
                "id": "AL", 
                "countryName": "Albania" 
            },
        },
        {
            "type": "Feature",
            "geometry": {
                "type": "Point",
                "coordinates": [41.0000, 20.0000]
                },
        },
    ]
}

推荐的方法是什么?

我已经有了一种方法,但看起来不太好,因为它只适用于 xslt 1.0(我认为)和文本块。 看这里:https://xsltfiddle.liberty-development.net/naZYrpy/1

我更喜欢使用 xslt 3.0 和 xml-to-json 函数的更有效方式,但似乎无法添加额外的 json 对象。

更多示例: 1. 不工作:https://xsltfiddle.liberty-development.net/pNmCzsA

  1. 不工作:https://xsltfiddle.liberty-development.net/ejivdGS/4

  2. 不工作:https://xsltfiddle.liberty-development.net/bFWR5DQ/17

提前致谢:-)

如果您想直接使用 XPath 3.1 创建 XDM 映射和数组以序列化为 JSON,请使用

 <xsl:sequence
    select="map { 'type' : 'FeatureCollection',
                  'Features' : array {
                    //item ! (
                      map {
                        'type' : 'Feature',
                        'properties' : map {
                          'radius' : TotalConfirmed div $max * 100,
                          'id' : data(CountryCode),
                          'countryName' : data(Country)
                        }
                      },
                      map {
                        'type' : 'Feature',
                        'geometry' : map {
                          'type' : 'Point',
                          'coordinates' : [number(Lat), number(Lng)]
                        }
                      }
                    )}
                }"/>

https://xsltfiddle.liberty-development.net/a9HjZi

请注意,像 Javascript 对象这样的 XDM 映射没有任何有序的属性集合,因此您可以通过这种方式定义序列化顺序,Saxon 9 和 10 的商业版为此提供了扩展。

或者您需要将输入 XML 转换为 XML 格式 xml-to-json 函数 exepcts,它将 XML 输入中元素的顺序保留为JSON序列化的输出顺序:

<?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"
    xmlns="http://www.w3.org/2005/xpath-functions"
    exclude-result-prefixes="#all"
    expand-text="yes"
    version="3.0">

  <xsl:output method="text"/>

  <xsl:variable name="max" select="max(//item/*[starts-with(local-name(), 'TotalConfirmed')]/xs:integer(.))"/>

  <xsl:template match="/">
     <xsl:variable name="xml-to-json-input">
         <map>
             <string key="type">FeatureCollection</string>
             <array key="features">
                 <xsl:apply-templates select="//item"/>
             </array>
         </map>
     </xsl:variable>

     <xsl:value-of select="xml-to-json($xml-to-json-input, map { 'indent' : true() })"/>
  </xsl:template>

  <xsl:template match="item">
      <map>
          <string key="type">Feature</string>
          <map key="properties">

              <number key="radius">{TotalConfirmed div $max * 100}</number>
              <string key="id">{CountryCode}</string>
              <string key="countryName">{Country}</string>
          </map>
      </map>
      <map>
          <string key="type">Feature</string>
          <map key="geometry">
              <string key="type">Point</string>
              <array key="coordinates">
                  <number>{number(Lat)}</number>
                  <number>{number(Lng)}</number>
              </array>
          </map>
      </map>
  </xsl:template>


</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/a9HjZi/2