MS RFC 86:基于比例的字符串替换

日期

2012/10/08

作者

托马斯堡

联系

tbonfort@terriscope.fr

状态

采用

版本

MAPServer 6.4

1。概述

当需要依赖于规模的数据源时,MapServer能够使用多个层,并将minscale/maxscale过滤组组合在一起,例如:

LAYER
  NAME "roads_far"
  GROUP "roads"
  TYPE LINE
  MINSCALE 100000
  DATA "the_geom from roads_far"
  CLASS
    ...
  END
  CLASS
    ...
  END
END
LAYER
  NAME "roads_close"
  GROUP "roads"
  TYPE LINE
  MAXSCALE 100000
  DATA "the_geom from roads_close"
  CLASS
    ...
  END
  CLASS
    ...
  END
END

虽然此解决方案有效,但不方便在多个层中复制符号,可能需要进行一些调整,以便在功能文档中隐藏多个层。

当前的RFC建议模拟当前的运行时替换机制来替换层数据语句中的令牌。代替使用一个url参数来完成替换,令牌被一个依赖于当前地图比例的值替换。

2。建议的解决方案

这里的例子价值千言万语…

2.1。例1

LAYER
  ..
  SCALETOKEN
    NAME "%priority%"
    VALUES
      "0" "1"
      "1000" "2"
      "10000" "3"
    END
  END
  DATA "the_geom from mytable_%priority%"  #data comes from a specific table
  DATA "/path/to/roads_%priority%.shp"  #data comes from a specific shapefile
  DATA "the_geom_%priority% from roads" #data comes from a specific column in the table
  DATA "the_geom_%priority% from (select * from roads where priority > %priority%) as foo" #data is filtered
  CLASS
    ...
  END
END

在上一个示例中,%优先级%将替换为:

  • 1000以下称为“1”,给出:

    DATA "the_geom from mytable_1"
    DATA "/path/to/roads_1.shp"
    DATA "the_geom_1 from roads"
    DATA "the_geom_1 from (select * from roads where priority > 1) as foo"
    
  • 1000到10000之间的刻度为“2”

    DATA "the_geom from mytable_2"
    DATA "/path/to/roads_2.shp"
    DATA "the_geom_2 from roads"
    DATA "the_geom_2 from (select * from roads where priority > 2) as foo"
    
  • “3”表示10000以上的天平

    DATA "the_geom from mytable_3"
    DATA "/path/to/roads_3.shp"
    DATA "the_geom_3 from roads"
    DATA "the_geom_3 from (select * from roads where priority > 3) as foo"
    

2.2例2

LAYER
  ..
  SCALETOKEN
    NAME "%table%"
    VALUES
      "0" "roads"
      "1000" "roads_gen_1"
      "10000" "roads_gen_0"
    END
  END
  DATA "the_geom from %table%"  #data comes from a specific table
  DATA "/path/to/%table%.shp"  #data comes from a specific shapefile
  CLASS
    ...
  END
END

在上一个示例中,%表%将替换为:

  • “道路”的比例尺小于1000,给出:

    DATA "the_geom from roads"
    DATA "/path/to/roads.shp"
    
  • 1000至10000之间的“道路”等级

    DATA "the_geom from roads_gen_1"
    DATA "/path/to/roads_gen_1.shp"
    
  • “道路”的等级超过10000

    DATA "the_geom from roads_gen_0"
    DATA "/path/to/roads_gen_0.shp"
    

2.3例3

LAYER
  ..
  SCALETOKEN
    NAME "%filter%"
    VALUES
      "0" ""
      "1000" "where type in ('motorway','trunk','primary')"
      "10000" "where type='motorway'"
    END
  END
  DATA "the_geom from (select * from roads %filter%) as foo"
  CLASS
    ...
  END
END

在上一个示例中,%filter%将替换为:

  • 不适用于1000以下的天平,给出:

    DATA "the_geom from (select * from roads) as foo"
    
  • “在其中键入(‘高速公路’、‘主干道’、‘主要’)用于1000到10000之间的比例”

    DATA "the_geom from (select * from roads where type in ('motorway','trunk','primary')) as foo"
    
  • “其中,当比例超过10000时,键入=‘高速公路’”

    DATA "the_geom from (select * from roads where type='motorway') as foo"
    

2.4讨论

  • 多个令牌可用于单个层,例如用于应用筛选器 and 正在命中通用表。

  • 在值块内,第一个缩放项 must 为“0”,条目 must 按升序排列。

  • 示例使用“%keyname%”表示法来模拟MapServer现有的URL运行时替换。未强制使用“%…%”符号,代码将执行简单的字符串替换。(即,“优先级”或“表”是有效值,前提是“优先级”或“表”子字符串出现在数据语句中。

  • 依赖于比例的替换将应用于层的数据、tileindex、tileitem、filteritem和filter。将它应用于其他元素可能是有意义的,但在对代码的影响方面更为重要。筛选器上依赖于刻度的替换可能与通过MapServer的WFS筛选器处理设置的筛选器不兼容。

  • bug 3150讨论了这种替换的必要性,但其范围更为有限。

  • 如果令牌具有在多个层中被替换的使命,那么最好在映射级别(而不仅仅是层级别)提供scaleToken条目。初始实现中将不存在映射级别的scaleToken。

  • 提供一个默认的令牌,以便在与缩放无关时使用(查询…)

三。实施细节

3.1概述

  • layerobj获取一个新成员,该成员包含适用的与缩放相关的标记。

  • 用于表示给定令牌的实际结构:

typedef struct {
  double minscale;
  double maxscale;
  char* value;
} scaleTokenEntryObj;

typedef struct {
  char* name;
  char* default_value;
  int n_entries;
  scaleTokenEntryObj* tokens;
} scaleTokenObj;

struct layerObj {
   ...
   scaleTokenObj* tokens;
   int numscaletokens;
   ...

   char* orig_data;
   char* orig_tileindex;
   char* orig_tileitem;
   ... etc ...
}
  • 在……里面 msLayerOpen() ,更换里面的代币 layerObj->datalayerObj->tileindex 等等..。原版 layerObj->data 预先存储在 layerObj->orig_data ,并在 msLayerClose()

  • 对于特殊情况: layerObj->filtermsLoadExpressionString() 在被替换的文本上被调用,以便更新表达式Obj。同样,它也会被调用 msLayerClose() 恢复原始筛选器时。

3.2受影响的文件

此RFC将修改/创建以下文件:

  • mapserver.h/mapfile.c:layerobj成员,mapfile关键字

  • mapcopy.c/mapfile.c:复制函数,写入文件函数

  • maplayer.c:调用mslayeropen()中的令牌替换,最终调用mslayerclose()。根据当前比例添加函数以应用替换。

  • maplexer.l:解析器关键字

3.3MapScript

在层scaleTokens上添加getter/setter

3.4向后兼容性问题

此更改提供了新的功能,没有考虑向后兼容性问题。

4。安全隐患

令牌在mapfile中定义,不能被url覆盖,因此与经典的数据语句相比,SQL注入或文件系统遍历的风险不会更大。

4。性能影响

令牌替换仅在mslayeropen()中完成,性能影响应忽略不计,因为每个呈现层仅发生一次。

5.错误ID

https://github.com/MapServer/MapServer/pull/4538

6。投票历史

+1人来自托马斯布、米克斯、汤克、丹尼尔、杰夫姆、史蒂文、史蒂文和佩林。