XSLT WMS GetCapabilities 到 JSON

Posted

技术标签:

【中文标题】XSLT WMS GetCapabilities 到 JSON【英文标题】:XSLT WMS GetCapabilities to JSON 【发布时间】:2021-08-07 01:03:18 【问题描述】:

我正在尝试将 GeoMet WMS XML response.data 的 GetCapabilities 转换为可用于 v-treeview Vuetify 组件(例如 in this link)的 JSON。

testfunc: function () 
      axios.get('https://geo.weather.gc.ca/geomet?lang=en&service=WMS&version=1.3.0&request=GetCapabilities').then((response) => 
        const xslt = `<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"
  xmlns:mf="http://example.com/mf"
  expand-text="yes"
    version="3.0">
  
  <xsl:strip-space elements="*"/>

  <xsl:output method="json" build-tree="no"/>
  
  <xsl:template match="/Layer" priority="5">
    <xsl:map>
      <xsl:apply-templates/>
    </xsl:map>
  </xsl:template>
  
  <xsl:template match="*[not(*)]">
    <xsl:map-entry key="local-name()" select="data()"/>
  </xsl:template>
  
  <xsl:template match="Layer[1]">
    <xsl:map-entry key="'children'">
      <xsl:sequence select="array  mf:apply-templates(*) "/>
    </xsl:map-entry>
  </xsl:template>
  
  <xsl:template match="Layer[position() > 1]"/>
  
  <xsl:function name="mf:apply-templates" as="item()*">
    <xsl:param name="elements" as="element(*)*"/>
    <xsl:apply-templates select="$elements"/>
  </xsl:function>
  
</xsl:stylesheet>`
        const jsonResult = SaxonJS.XPath.evaluate(`
          transform(
            map  
              'source-node' : parse-xml($xml), 
              'stylesheet-text' : $xslt, 
              'delivery-format' : 'raw' 
            
            )?output`,
        [],
         'params':  'xml': response.data, 'xslt': xslt  
        )
        console.log(jsonResult)
      )
    

我的测试函数返回所有信息,并没有真正按照我需要的方式解析 XML 响应,而且我是 XSLT 的新手。我需要一些只返回 &lt;Layer&gt; 标签的 &lt;Name&gt;&lt;Title&gt; innerhtml 以及它们在名为 children 的数组中的子元素,如下所示:


title: 'Title Level 1'
name: 'Name Level 1'
children: [
    
     title: 'Title Level 2'
     name: 'Name Level 2'
     children: [
         
          title: 'Title Level 3-1'
          name: 'Name Level 3-1'
         ,
         
          title: 'Title Level 3-2'
          name: 'Name Level 3-2'
         
     ]
]

编辑:full XML 的示例 XML,它有一个根,只有一个标题,它有 14 组

<Layer queryable="1">
<Title>MSC GeoMet — GeoMet-Weather 2.14.1</Title>
   <Layer queryable="1">
   <Name>Regional Deterministic Prediction System (RDPS) [10 km]</Name>
   <Title>Regional Deterministic Prediction System (RDPS) [10 km]</Title>
      <Layer queryable="1">
      <Name>RDPS - Coupled to Gulf of St. Lawrence (RDPS-CGSL)</Name>
      <Title>RDPS - Coupled to Gulf of St. Lawrence (RDPS-CGSL)</Title>
         <Layer queryable="1" opaque="0" cascaded="0">
         <Name>CGSL.ETA_ICEC</Name>
         <Title>CGSL.ETA.ICEC - Ice cover fraction</Title>
...

【问题讨论】:

不清楚您的输入 XML 格式是什么,所以至少显示一个小但有代表性的示例。 我已在原始帖子的编辑中添加了指向完整 XML Honnen 先生的链接和一个非常小的示例。有嵌套的图层标签,所有这些标签都有名称和标题,我需要所有的名称和标题,这样我就可以构建一个树视图可视化器。 如果您缩进样本并将其剪切以包含基本数据,这将有所帮助。一个图层可以有多个名称或多个标题子元素吗?在这种情况下你想创建什么样的 JSON? 请注意:我向您介绍了 SaxonJS.XPath.evaluate 作为直接运行 XSLT 代码的一种方式,但考虑到在浏览器和 Node.js 中更有效的方式是从使用 Saxon EE 或 xslt3 命令行工具将基于 XML 的 XSLT 代码转换为基于 JSON 的 SEF 格式,然后只需运行 SaxonJS.transform javascript 方法即可执行 SEF 代码。 【参考方案1】:

仅处理 Layer 元素(在该特定命名空间 http://www.opengis.net/wms 中)和第一个 TitleName 以及递归子 Layers 的 XSLT 3 示例将是

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:mf="http://example.com/mf"
    exclude-result-prefixes="#all"
    xpath-default-namespace="http://www.opengis.net/wms"
    xmlns="http://www.w3.org/2005/xpath-functions"
    expand-text="yes"
    version="3.0">

  <xsl:strip-space elements="*"/>
  
  <xsl:mode on-no-match="shallow-skip"/>

  <xsl:output method="json" build-tree="no" indent="yes"/>
  
  <xsl:template match="/WMS_Capabilities/Capability/Layer" priority="5">
    <xsl:map>
      <xsl:apply-templates/>
    </xsl:map>
  </xsl:template>
  
  <xsl:template match="Layer/Title[1] | Layer/Name[1]">
    <xsl:map-entry key="local-name()" select="data()"/>
  </xsl:template>
  
  <xsl:template match="Layer[1]">
    <xsl:map-entry key="'children'">
      <xsl:sequence select="array  ../Layer/mf:apply-templates(.) "/>
    </xsl:map-entry>
  </xsl:template>
  
  <xsl:template match="Layer[position() > 1]"/>
  
  <xsl:function name="mf:apply-templates" as="item()*">
    <xsl:param name="elements" as="element(*)*"/>
    <xsl:map>
      <xsl:apply-templates select="$elements/*"/>      
    </xsl:map>
  </xsl:function>
  
</xsl:stylesheet>

【讨论】:

你声称我是一名崇拜者,我谴责假神 Dimitre Novatchev 和 Michael Kay。非常感谢先生。您的解决方案非常完美,因此我想我更了解 XSLT。 不要做 Dimitre 或 Michael 的不公正行为,感谢 Michael 的努力(和 Saxonica 公司),我们拥有 XSLT 2 和 3 规范以及规范的 Saxon 实现,包括在浏览器和 Node.js,浏览器供应商或 JavaScript 公司肯定不会做出任何努力来支持 XML 相关的创新。 Dimitre 成为 *** 上第一位 XML 和 XSLT 金牌明星是有原因的,他的 XPath Visualizer 无疑是帮助我多年前进入 XSLT 和 XPath 世界的工具。

以上是关于XSLT WMS GetCapabilities 到 JSON的主要内容,如果未能解决你的问题,请参考以下文章

使用 Javascript DOM 解析器从 WMS GetCapabilities 请求的 XML response.data 中提取层列表

怎么解决百度地图API得到的坐标误差

leaflet怎么加载天地图的wmts服务

如何从地理服务器获取图层列表

xml WFS GetCapabilities v1.0.0

QGIS 是不是支持 WMS-T(WMS with time)?