• SQL Server 2008空间数据应用系列十:使用存储过程生成GeoRSS聚合空间信息


    友情提示,您阅读本篇博文的先决条件如下:

      1、本文示例基于Microsoft SQL Server 2008 R2调测。

      2、具备 Transact-SQL 编程经验和使用 SQL Server Management Studio 的经验。

      3、熟悉或了解Microsoft SQL Server 2008中的空间数据类型。

      4、具备相应(比如OGC规范、KML规范)的GIS专业理论知识。

      5、其他相关知识。


      GeoRSS是一种描述和查明互联网内容所在物理位置的方法。通过使用GeoRSS,搜索Web站点或者与地理位置有关的项目就成为可能。GeoRSS利用地理标识语言(GML),即利用可扩展标记语言 (Extensible Markup Language, XML)存储和传输地理数据的方法。原始的GML模型以由World Wide Web联盟(W3C)所开发的资源描述框架(RDF)为基础。GML保持着RDF的许多特性,包括智能代理和一个用于描述和查询数据的标准语法。GeoRSS 是在 RSS 订阅源中包含地理空间数据时所用的一个标准,它定义了一种名为 GeoRSS GML 的特定格式,用来在订阅源中包含 GML 格式的数据。客户端应用程序可以订阅 GeoRSS 订阅源,订阅方式与订阅常规 RSS 订阅源相同。可以轻松地将 GeoRSS 格式的数据导入Microsoft Bing Maps、Google Maps中。

    一、GeoRSS聚合格式

      相信很多朋友多玩过RSS订阅的,其聚合数据的格式以XML方式承载,主要包括头信息和体信息,体信息可能是一项或多项的数据组成。以下为RSS的聚合格式:

    <?xml version=“1.0” en coding=“gb2312”?> 
    <rss version=“2.0”> 
       
    <channel> 
          
    <title>网站或栏目的名称</title> 
          
    <link>网站或栏目的URL地址</link> 
          
    <description>网站或栏目的简要介绍</description> 
          
    <item> 
             
    <title>新闻标题</title> 
             
    <link>新闻的链接地址</link> 
             
    <description>新闻简要介绍</description> 
             
    <pubDate>新闻发布时间</pubDate> 
             
    <author>新闻作者名称</author> 
          
    </item> 
          
    <item> 
            …… 
           
    </item> 
       
    </channel> 
    </rss>

      而GeoRSS的XML数据格式和RSS几乎相同,只是在RSS的基础上使用GML扩展了对于地理空间数据的描述信息,如下GeoRSS数据。

    <feed
      
    xmlns="http://www.w3.org/2005/Atom"
      xmlns:georss
    ="http://www.georss.org/georss"
      xmlns:gml
    ="http://www.opengis.net/gml"
      
    >
      
    <entry>
        
    <id>urn:uuid:7e8ee974-9181-4eae-ad65-55d29175d942</id>
        
    <link href="http://example.org/entries/1"/>
        
    <title>Cedarburg Trip</title>
        
    <summary>We went to visit downtown Cedarburg before the
        conference. Had some great sandwiches at Joe's. If you
        haven't been to Cedarburg, Wisconsin, then you haven't
        really experienced the MidWest...
    </summary>
        
    <content type="html" src="http://example.org/entries/1"/>
      
    </entry>
      
    <entry>
        
    <id>urn:uuid:53664db3-4598-45d4-a727-022c6203322e</id>
        
    <link rel="related" href="http://example.org/entries/1"/>
        
    <title>Downtown Cedarburg, Wis.</title>
        
    <summary>Went to visit downtown Cedarburg...</summary>
        
    <georss:where>
          
    <gml:Point>
            
    <gml:pos>43.296700 -87.98750</gml:pos>
          
    </gml:Point>
        
    </georss:where>
      
    </entry>
      
    <entry>
        
    <id>urn:uuid:2528d1b4-b5a9-415c-be69-f83974e3e6af</id>
        
    <link rel="related" href="http://example.org/entries/1"/>
        
    <title>Convention Center</title>
        
    <georss:where>
          
    <gml:LineString>
            
    <gml:posList>43.296700 -87.987500 43.3 -88 -44 -89</gml:posList>
          
    </gml:LineString>
        
    </georss:where>
      
    </entry>
    </feed>

            

    二、GeoRSS空间编码

      通常有三种GeoRSS编码,既简单编码、GML编码和W3C编码。详细请查阅:http://www.georss.org/Encodings

      简单编码通常用于定义点、线、多边形等规则的空间数据,GML则通常适用于定义不规则的空间数据,如地市区域。

    三、定义GeoRSS数据

      定义GeoRSS数据其实主要就是在玩GeoRSS空间编码,知道如何定义点、线、多边形以及不规则的空间图形。如下GeoRSS定义了一个点(重庆)坐标。

    <?xml version="1.0" encoding="utf-8"?>
    <feed xmlns="http://www.w3.org/2005/Atom" 
      xmlns:georss
    ="http://www.georss.org/georss">
      
    <title>重庆</title>
      
    <subtitle>重庆坐标</subtitle>
      
    <link href="http://example.org/"/>
      
    <updated>2011-3-25 23:34:26</updated>
      
    <author>
        
    <name>Beniao</name>
        
    <email>beniao@live.cn</email>
      
    </author>
      
    <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
      
    <entry>
        
    <title>ChongQing</title>
        
    <link href="http://example.org/2005/09/09/atom01"/>
        
    <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
        
    <updated>2011-3-25 23:35:00</updated>
        
    <summary>summary>
        
    <georss:point>29.5076372217973 106.489384971208</georss:point>
      
    </entry>
    </feed>

      同样的定义一条空间线段,只是使用的GeoRSS编码不同,如下定义了【成都--重庆】的空间线段示例。

    <georss:line>30.6666587469201 104.062021177233 29.5076372217973 106.489384971208</georss:line>

    四、创建GeoRSS聚合存储过程

      创建GeoRSS聚合存储过程的作用就是将空间数据格式化为GeoRSS的数据格式,存储过程中实现查询空间数据,转换空间数据为GML后并构造为GeoRSS的数据输出。《SQL Server 2008空间数据应用系列九:使用空间工具(Spatial Tools)导入ESRI格式地图数据》一文中实现了将shp数据导入到SQL Server 2008中,本篇以此数据为例创建存储过程发布GeoRSS。

            

    USE [BingMapsDB]
    GO

    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    CREATE PROCEDURE [dbo].[CQGeoRSSFeeder]
    AS
    BEGIN

    SET NOCOUNT ON;

    -- 定义XML类型变量用于存储GeoRSS内容
    DECLARE @GeoRSS xml;

    WITH XMLNAMESPACES (
      
    'http://www.opengis.net/gml' AS gml,
      
    'http://www.georss.org/georss' AS georss
    )
    SELECT @GeoRSS =
      (
    SELECT
        
    [NAME] AS title,
        
    [NAME] AS description,
        
    'http://www.beginningspatial.com/' + CAST([ID] AS varchar(8)) AS link,
        geom.AsGml() 
    AS [georss:where]
      
    FROM
        CQ_Region
      
    FOR XML PATH('item'), ROOT('channel')
    )

    /**
     * 使用XQuery格式化XML结果 
     *
    */
    SELECT @GeoRSS.query('
    <rss version="2.0"
      xmlns:georss="http://www.georss.org/georss"
      xmlns:gml="http://www.opengis.net/gml">
    <channel>
      <title>SQL Server 2008 GeoRSS</title>
      <description>GeoRSS数据描述</description>
      <link>http://www.beginningspatial.com</link>
      {
        for $e in channel/item
        return
        <item>
        <title> { $e/title/text() }</title>
        <description> { $e/description/text() }</description>
        <link> { $e/link/text() }</link>
        <pubDate>  { $e/pubDate/text() }</pubDate>
        <georss:where>
          {
            for $child in $e/georss:where/*
            return
            if (fn:local-name($child) = "Point") then  <gml:Point> { $child/* } </gml:Point>
            else  if (fn:local-name($child) = "LineString") then  <gml:LineString> { $child/* } </gml:LineString>
            else  if (fn:local-name($child) = "Polygon") then  <gml:Polygon> { $child/* } </gml:Polygon>
            else  if (fn:local-name($child) = "MultiPoint") then  <gml:MultiPoint> { $child/* } </gml:MultiPoint>
            else  if (fn:local-name($child) = "MultiCurve") then  <gml:MultiCurve> { $child/* } </gml:MultiCurve>
            else  if (fn:local-name($child) = "MultiSurface") then  <gml:MultiSurface> { $child/* } </gml:MultiSurface>
            else  if (fn:local-name($child) = "MultiGeometry") then  <gml:MultiGeometry> { $child/* } </gml:MultiGeometry>
            else  ()
          }
        </georss:where>
      </item>
      }
    </channel>
    </rss>
    'AS GeoRSSFeed;
    end

      注:执行该存储过程后的就可以将表中所有的空间数据建立GeoRSS输出,输出内容比较大,这里就不贴XML结果了,随本文末的示例代码一起提供给大家下载。

    五、.NET发布GeoRSS订阅

      .NET服务端可以通过ASPX、ASHX等方式来发布GeoRSS订阅服务,这一步其实非常简单,就是直接调用上面的存储过程,见数据库中的空间数据以GeoRSS的数据格式输出到客户端呈现即可。以下为详细的代码实现:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Data.SqlClient;

    namespace GeoRSSService
    {
        
    /// <summary>
        
    /// 发布SQL Server 2008中的空间数据为GeoRSS。
        
    /// </summary>
        public class GeoRSSHandler : IHttpHandler
        {
            
    public void ProcessRequest(HttpContext context)
            {
                context.Response.ContentType 
    = "text/xml";
                context.Response.Charset 
    = "iso-8859-1";
                context.Response.CacheControl 
    = "no-cache";
                context.Response.Expires 
    = 0;

                SqlConnection myConn 
    = new SqlConnection(
                    
    @"server=.;database=BingMapsDB;uid=sa;pwd=beniao;");
                myConn.Open();

                
    string myQuery = "exec dbo.CQGeoRSSFeeder";
                SqlCommand myCMD 
    = new SqlCommand(myQuery, myConn);
                SqlDataReader myReader 
    = myCMD.ExecuteReader();

                
    while (myReader.Read())
                {
                    
    //输出GeoRSS到客户端
                    context.Response.Write(myReader["GeoRSSFeed"].ToString());
                }

                myReader.Close();
                myConn.Close();
            }

            
    public bool IsReusable
            {
                
    get
                {
                    
    return false;
                }
            }
        }
    }

        

    六、相关资料

      [1]、RSS官网:http://www.georss.org/georss

      [2]、RSS简介:http://baike.baidu.com/view/1644.htm

      [3]、GML简介:http://baike.baidu.com/view/609279.htm

  • 相关阅读:
    sql函数
    sql日期
    Windows下串口编程
    Libreoffice/Office:禁止首字母自动大写功能
    convert:图片转pdf失败
    LibreOffice/Calc:单元格设置下拉菜单
    Ubuntu:查询计算机软硬件信息
    tar:文件打包归档
    中科大自主招生2018年笔试数学之五
    文件分割与合并
  • 原文地址:https://www.cnblogs.com/beniao/p/1995939.html
Copyright © 2020-2023  润新知