ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

ArcMap-MXD专题图转GeoServer发布:SLD样式转换全流程实战

ArcMap-MXD专题图转GeoServer发布:SLD样式转换全流程实战 最近在弄一个老项目的Web化迁移手里攒了一堆ArcMap做好的MXD专题图客户要求搬到GeoServer上发布。GeoServer本身能跑WMS、WFS但默认样式实在没法看只有最基础的颜色填充。要让Web端地图长得和ArcMap里的专题图一致把MXD里的符号系统直接转成SLD是目前最靠谱的路径。我顺着arcmap2SLD这个方向摸索把从MXD到SLD、再从SLD到GeoServer发布的整条链路跑通了。这篇就把完整流程和我在实战中踩过的坑整理出来做一个可以照着抄的作业。1. MXD那套符号体系和SLD到底差在哪为什么必须转换1.1 两套渲染模型的距离MXD是ArcMap的工程文档里面保存了图层列表、数据源连接信息、符号系统Symbology和标注设置。符号系统是ESRI私有的渲染方案常见的有单一符号渲染Simple、唯一值渲染Unique Values、分级渲染Class Breaks、比例符号渲染等几种模式。每种模式下的符号对象也不一样面用FillSymbol线用LineSymbol点用MarkerSymbol标注走的是LabelExpression。这些信息全部埋在MXD的二进制结构里要用ArcMap打开才能看到别的软件基本读不出来。SLD的全称是Styled Layer Descriptor是OGC开放地理空间联盟制定的标准用XML文本来描述一个图层应该怎么被渲染。GeoServer、MapServer这些开源GIS服务器都认这个格式。SLD的核心模型是StyledLayerDescriptor根节点下面挂NamedLayer和UserStyleUserStyle里面是FeatureTypeStyleFeatureTypeStyle里面是一条条RuleRule可以带Filter用来筛选要素也可以带MinScaleDenominator和MaxScaleDenominator来控制显示的缩放级别范围最后落到具体执行渲染的Symbolizer。Symbolizer分成PolygonSymbolizer面、LineSymbolizer线、PointSymbolizer点、TextSymbolizer标注、RasterSymbolizer栅格这几种基本类型。可以这么理解MXD里的符号系统是ESRI的语言SLD是开源GIS世界的通用语言。GeoServer不认MXD只认SLD。把MXD搬到GeoServer就必须经过一个翻译过程。这跟翻译外语差不多有些词能直译有些文化梗就翻不了翻译得怎么样取决于翻译官的水平。arcmap2SLD就是干这个活的翻译官。1.2 arcmap2SLD能做什么、不能做什么arcmap2SLD工具的原理是基于ArcObjects写了一个ArcGIS Desktop的插件运行时通过ArcObjects读取当前MXD文档里每个图层的Renderer和Symbol按照ESRI符号模型到OGC SLD模型的映射关系逐个图层、逐条规则地生成XML最后写出一个或多个SLD文件。因为是ArcObjects开发的所以这个工具必须跑在安装了ArcGIS Desktop的Windows机器上而且得有可用的许可。我实际测试下来这些场景转换效果比较理想简单面填充纯色填充、边框线颜色和宽度稳定输出PolygonSymbolizer唯一值渲染按字段值分颜色每类值生成一条Rule加Filter条件分级渲染按数值范围分档每档一条Rule用数值范围Filter控制简单线符号颜色、线宽、虚线样式能转成LineSymbolizer基础点符号圆形、方形、三角形这类可识别的WellKnownName标记字段标注能转成TextSymbolizer不太完美的地方也很明显MXD里用了制图表达Representation的图层转换工具基本无能为力要么忽略要么退化成普通符号ArcMap自带的那些特殊字符标记符号比如交通标志、树形符号、水滴形符号转出来容易变成不认识的形状或者退化成默认圆形依赖外部图片的点符号转换后会生成ExternalGraphic引用图片路径对不上就显示成叉或空白如果已经是ArcGIS Pro的项目文件.aprx这些老工具不一定支持这里特别说一下专题图图例模板mxd这个场景。很多人手头有的是做好的一套带图例框、指北针、比例尺的MXD模板想把整套版式搬到Web端。但SLD描述的是数据图层的渲染方式不包含图例框、指北针这些版式元素。转换之前要先把这些版面元素从目标图层中剥离Web端的图例是OpenLayers、Leaflet这些前端框架读取样式后自己生成的不是从MXD里搬过去的。2. 动手前的底数装好GeoServer也把MXD收拾利索2.1 GeoServer的安装GeoServer是Java写的Web应用第一步是装JDK。不同版本的GeoServer对JDK版本要求不一样比如GeoServer 2.23.x配JDK 11比较稳2.25.x需要JDK 17。我先查了官方文档要求再装对应版本这一步别省版本对不上启动就报错。安装方式我习惯用zip绿色包省去安装向导的麻烦。从官网下载对应平台的zip压缩包解压到一个没有中文和空格的路径下比如D:\GeoServer。然后确认环境变量JAVA_HOME指向正确的JDK安装目录。Windows下双击bin目录里的startup.bat启动Linux下运行startup.sh等控制台出现Started之类的日志后浏览器访问http://localhost:8080/geoserver/web默认用户名是admin密码是geoserver。启动阶段常见的坑有三个第一8080端口被别的程序占了启动脚本一闪而过。解决方法是关掉占用端口的程序或者修改GeoServer的端口配置老版本在web.xml里改新版在jetty.xml里改具体以版本文档为准。第二JAVA_HOME没配好双击startup.bat后窗口一闪就没反应。在命令行里运行一下startup.bat能看到具体的报错信息缺什么补什么。第三下载太慢。GeoServer官网下载有时候很慢可以找国内镜像站搜索GeoServer 镜像下载就能找到。2.2 MXD源文件的前处理转换前先把MXD收拾干净能省掉后面80%的排查工作这是我从多次失败里总结出来的。第一个规则确认所有图层的数据源路径有效。MXD里存的是数据源绝对路径如果你把MXD从一台机器复制到另一台机器打开时经常提示数据源断链。最好先把所有SHP、GDB统一放到一个目录下重新添加一遍数据源确保每个图层都能正常显示。第二个规则把不打算搬到GeoServer的图层删掉。MXD里常有的指北针框、比例尺条、图例框、辅助说明图层这些在Web端用不到留着只会增加转换工具的处理负担。可以用图层属性里的可见性控制或者在转换时直接只勾选目标图层。第三个规则简化符号系统。能用标准符号就不用自定义符号能用纯色填充就不用渐变和图片填充能用实线就不用复杂线型。这不是偷懒而是很多ArcMap特有的符号效果在SLD标准里原本就不支持转换过去也是丢不如在设计阶段就换成Web端表现最稳定的方案。第四个规则确认坐标系。MXD里的数据坐标系要明确是EPSG:4326还是EPSG:3857还是CGCS2000高斯克吕格投影心里要有数。如果数据本身没有坐标系信息转换出来的SLD在GeoServer里挂上去后图层位置会错得很离谱。第五个规则图层命名尽量用英文。MXD里的图层名带中文的话转换出来的SLD内部名称可能也带中文后面在GeoServer里调试URL、写Filter的时候会很难受。建议在ArcMap里先把图层重命名成英文比如boundary、road、station这种。2.3 准备小范围测试数据不要一上手就拿全省全网数据测试。我建议从MXD里裁剪出一小块区域比如一个区的边界、两条主干道、几个关键站点覆盖面、线、点、标注四种类型就行。这样转换和排查速度都快如果出了问题也很容易定位是转换环节还是发布环节的锅。这个测试步骤看起来不起眼实际价值很大。我第一次直接用全套数据转出来的SLD有几百条Rule在GeoServer里一加载就白屏根本不知道问题出在哪个图层。后来换小数据测几分钟就能定位是哪一层符号转换异常。3. 核心流程arcmap2SLD一步步把MXD翻成SLD3.1 工具的加载和准备arcmap2SLD安装完成之后一般会在ArcMap里出现一个工具条或者工具箱入口。打开ArcMap的菜单栏在自定义里找到工具条或者扩展模块把对应的项勾选上工具条就会出现在界面上。不同版本的工具名称和菜单位置可能略有差异这个以实际安装版本为准。另外在动手之前先建一个干净的输出目录专门放转换生成的SLD文件。后续上传到GeoServer时也从这个目录里选文件文件多了不会乱。我习惯按项目建目录比如D:\sld_output\文件名写成图层名_日期.sld这样的格式方便版本备份。3.2 执行转换的步骤转换操作的大致流程是打开工具对话框工具条上通常有一个导出按钮或者菜单项选择要导出的图层。支持勾选多个图层也可以选择当前地图全部图层但我更推荐逐个图层导出后面解释原因设置输出SLD文件的路径和文件名设置转换选项比较常见的有四类是否把标注Label转成TextSymbolizer是否把外部图片符号内嵌为Base64有些版本支持这个选项是否输出比例尺分母范围如果MXD里设置了可见比例范围坐标参考系的处理方式点击执行等待生成完成为什么推荐每个图层单独导出因为GeoServer里的样式是跟图层一对一关联的每个图层在样式管理里都有一条独立的记录。一个MXD导出成一个大的SLD里面包含所有图层的FeatureTypeStyle上传时还得拆开用。图层多了以后单独导出、单独管理、单独排查效率高很多。实际操作的时候遇到一个问题工具把MXD里所有图层的符号都导出到了同一个SLD文件里包括透明参考图层。后来我改成先取消勾选不要的图层再转换输出的文件干净很多。3.3 用XML编辑器检查生成结果拿到SLD文件后用Notepad、VS Code等带XML语法高亮的编辑器打开看一眼。不要急着上传先把SLD的关键节点过一遍。先看根节点StyledLayerDescriptor和version属性接着看NamedLayer的Name字段是否跟预期一致。然后看UserStyle下面的FeatureTypeStyle数量如果是单一图层导出正常应该只有一个FeatureTypeStyle。再看FeatureTypeStyle里有几条Rule特别是分级渲染每一档应该对应一条Rule如果Rule数量跟MXD里的分级档位数对不上说明转换有问题。最后检查Symbolizer类型是否正确。面图层应该出现PolygonSymbolizer线图层出现LineSymbolizer点图层出现PointSymbolizer标注出现TextSymbolizer。如果面图层的Rule里写的是LineSymbolizer那说明工具把面当线处理了要回ArcMap里去检查数据源类型。下面是一个典型的单一图层面符号SLD骨架StyledLayerDescriptor version1.0.0 xmlnshttp://www.opengis.net/sld NamedLayer Nameboundary/Name UserStyle FeatureTypeStyle Rule PolygonSymbolizer FillCssParameter namefill#FFCC00/CssParameter/Fill Stroke CssParameter namestroke#000000/CssParameter CssParameter namestroke-width1/CssParameter /Stroke /PolygonSymbolizer /Rule /FeatureTypeStyle /UserStyle /NamedLayer /StyledLayerDescriptor如果看到Rule里面是空的Symbolizer或者PolygonSymbolizer里面缺少Fill参数那多半是源图层在ArcMap里没有设置有效的符号回到MXD里把符号设置好再转一次。3.4 一套典型样例的转换对照我用一个交通专题图的MXD举例这个案例能代表大部分常规情况。MXD中三个图层区县边界面、道路线、站点点。区县边界按所属区域字段做唯一值渲染三个区域三色道路按等级字段区分样式高速8号宽、国道6号宽、县道3号宽颜色用深浅区分站点用圆点符号8磅大小黑色边框加红色填充区县名称和站名有标注。转换出来的SLD里区县面一个FeatureTypeStyle里面有三条Rule每条Rule的Filter用PropertyIsEqualTo匹配所属区域字段的不同值PolygonSymbolizer分别填充三种颜色道路线三条Rule用PropertyIsEqualTo匹配等级字段LineSymbolizer里的Stroke宽度分别是8、6、3站点一条RulePointSymbolizer里是Mark符号WellKnownName为circle设置了Size和Fill、Stroke标注TextSymbolizer出现在对应的图层Rule里包含Font、Fill、Halo等节点Label是字段名引用这个结构算是标准答案了。如果你的SLD跟这个差异很大比如道路线变成了一个PolygonSymbolizer或者站点的PointSymbolizer变成了ExternalGraphic引用那就需要手工检查和调整。4. 把SLD送进GeoServer发布服务、挂样式、看效果4.1 GeoServer中怎么选择矢量数据发布服务GeoServer发布矢量数据的核心链路是创建Workspace工作空间 - 添加Store数据存储 - 发布Layer图层 - 关联Style样式。登录GeoServer管理界面之后左侧菜单找到工作区Workspaces点击添加新的工作区填一个英文字母命名的名称比如trafficURL可以随便填一个一般写项目域名或空着也行。接下来点数据存储Stores- 添加新的数据存储这时候会出现一个巨大的数据源类型列表。很多人到这里就懵了不知道选哪个。这就是geoserver怎么选择矢量数据发布服务这个问题最常见的困惑点。其实本质就是选择Store类型跟你要发布的数据格式强相关。我常用的几种数据源对比如下数据源类型适用场景说明Shapefile中小数据量文件型最简单放好路径就能用PostGIS大数据量、需事务处理需要PostgreSQLPostGIS扩展GeoPackage单文件多图层比Shapefile对属性支持更好矢量文件目录批量发布多个SHP选目录后一次发布目录内所有SHP如果你手头就是Shapefile选Shapefile填数据源名称然后把路径指到SHP文件所在位置。路径可以填绝对路径也可以先把数据放到GeoServer数据目录下的data目录里再填相对路径。我推荐放data目录的做法因为整个GeoServer目录打包迁移时数据也跟着走不容易出现路径失效的问题。如果是PostGIS里的数据选PostGIS - PostGIS数据库需要填主机、端口、数据库名、schema、用户名和密码。注意在PostgreSQL里要预先创建好数据库并启用PostGIS扩展不然连接会报错提示找不到postgis相关函数。还有一个很实用的场景如果你有一整个目录的SHP文件逐个添加太累。这时候选矢量文件目录Directory of spatial files类型填目录路径GeoServer会自动扫描目录里的所有Shapefile并批量发布成图层省事很多。4.2 图层的发布配置Store创建成功后点左侧菜单图层Layers- 添加新的资源展开刚创建的数据存储就能看到里面的数据集合列表。找到目标数据集点右边的发布按钮进入图层配置页面。发布页面有几个必填项我逐个说一下Native SRS数据源自身的坐标系。GeoServer一般能自动读取Shapefile的.prj文件如果读取不到会显示Unknown这时候必须手动从列表里选坐标系ID。比如数据是WGS84经纬度就选EPSG:4326是Web墨卡托就选EPSG:3857是CGCS2000高斯克吕格3度带就选对应的EPSG代码Declared SRS对外发布的坐标系声明。这里一般建议声明为EPSG:4326或EPSG:3857按业务需要来。客户如果要求在网页上叠加标准底图天地图、OSMEPSG:3857是主流选择边框Bounding Boxes这里有个从数据的边界框计算按钮点一下GeoServer会自动根据数据量算出经纬度范围和原生坐标系范围。这个操作一定要做如果边框是空的发布后预览就是空白配置好这三个点之后点击保存。图层发布完成这时候在图层列表应该能看到刚才发布的图层了。如果只是要验证数据本身有没有问题可以先不改样式用GeoServer自带的默认样式预览一下。看到数据能正常显示再做样式关联。4.3 SLD样式上传与图层关联样式管理在左侧菜单样式Styles里。点击添加新的样式页面里有两个标签页一个是直接编辑SLD内容另一个是上传样式文件。我习惯用上传的方式因为arcmap2SLD生成的是完整文件不用复制粘贴。点上传样式标签页选择本地生成的SLD文件然后最关键的一步先点验证按钮。GeoServer会检查SLD语法是否正确如果格式有问题会给出明确的报错信息。验证通过后再点提交样式就保存进去了。样式名称会自动生成我建议改成跟图层对应的英文名比如traffic_road_style方便后面找。样式创建好了之后回到图层页面找到目标图层点进去在发布页签或者样式相关配置区域把默认样式改成刚上传的SLD样式。保存后点击预览图层Layer Preview在预览方式里选OpenLayers就能看到实际渲染效果了。如果预览结果跟ArcMap里差距很大先别急着改SLD按下面这个顺序排查确认样式真的关联到了图层上确认图层的数据源坐标系声明正确边框范围计算了确认SLD里的Symbolizer类型跟图层几何类型匹配确认没有遗留的Filter把要素过滤掉了4.4 调试样式的小技巧GeoServer的图层预览是调试最快路径不需要写任何前端代码。还有几个实用技巧可以分享一下第一样式编辑页面里那个验证按钮是宝贝。SLD写错标签、漏掉闭合它都能指出具体行和原因比跑预览看白屏高效太多。第二遇到Filter条件不生效的时候用WFS的GetFeature请求把图层的真实属性值拉出来看看。比如怀疑所属区域字段的值不对直接在浏览器里访问WFS的GetFeature URL返回的GML数据里能看到字段到底存的是什么值是不是跟前端看到的显示值不一致。这个方法帮我解决过好几个棘手的过滤问题。第三临时往SLD里加一个明显的标记。比如在出问题的图层上加一个Width更大的辅助线或者把填充色改成纯红方便肉眼确认是不是这个图层、这条Rule在生效。排查完再改回去就行。5. 最容易翻车的细节字体、符号、分级和坐标系5.1 中文标注和字体的兼容问题GeoServer渲染文字用的是运行服务器上的Java字体环境。如果SLD里写的是宋体、微软雅黑而跑GeoServer的服务器是Linux且没装这些字体标注就会变成方块或者干脆不显示。这个问题在生产部署时特别常见Windows本机测试没问题一上Linux服务器就乱了。解决办法有两个方向。一是给服务器补中文字体Ubuntu上装fonts-wqy-microhei或者fonts-noto-cjk这类字体包CentOS/RHEL上可以用yum安装wqy-zenhei-fonts二是把SLD里的字体名称改成服务器上确实存在的字体比如Noto Sans CJK SC。另外SLD文件编码也会导致乱码。如果文件本身是GBK编码GeoServer解析时容易乱码。转换工具生成的一般是UTF-8但如果你用记事本编辑过且改了编码格式就埋雷了。统一规范所有SLD文件一律UTF-8编码。还有一坑MXD里属性字段用了中文别名转换后在SLD的Filter里出现部分数据库连接和驱动对中文别名的兼容性不好。建议在ArcMap里就用英文或拼音字段名比如name、type、level。5.2 点符号丢失和图片路径问题点图层是最容易出问题的地方。在ArcMap里用一个水滴形、人形、树形符号这些属于ESRI字体符号库转换工具如果识别不了就会退化成X或者默认圆形。你自己安装的特殊字体符号比如路标、地铁标志GeoServer服务器上没装这个字体显示必然不对。如果是这样的问题处理思路是两条第一种转换完成后打开SLD看PointSymbolizer节点如果是ExternalGraphic确认OnlineResource里的URL地址可以被GeoServer访问到。如果是按相对路径写的要搞清楚这个相对路径是相对于哪个目录的最好把图片放到GeoServer能访问的固定目录或者直接用绝对URL。第二种如果图片路径没法保证稳定访问干脆在MXD里就统一替换成基础形状的符号。圆形、方形、三角形这些Mark符号在SLD里表现很稳定Web端视觉上也干净。ArcMap里大量使用自定义图片符号的专题图并不适合直接转换需要提前准备好替代方案。线条的虚线样式也容易出偏差。SLD中DashArray是以像素为单位的数组比如8 4 2 4如果转换工具没有处理好单位换算虚线会变得过密或者过疏。遇到这种问题直接手动调DashArray数值就行。面填充里那些斜线、点阵填充样式转换后多数会丢失或变成纯色。SLD标准本身对面填充图案的支持就有限建议在ArcMap里直接改成纯色加透明度这是Web端最稳妥的方案。5.3 分级渲染的边界值与Filter写法分级渲染是转换中逻辑最容易出微妙问题的地方。ArcMap的ClassBreaksRenderer每一档有自己的上界和下界转换到SLD之后变成两条比较条件组合成的一个范围Filter。常见的问题是这样的ArcMap的分级边界处理方式和SLD的Filter比较逻辑不完全吻合导致某些正好落在边界上的值哪一条Rule都不匹配。比如某要素的值正好等于8ArcMap里归入8-10档但SLD里写的Filter是大于等于8且小于10如果写成了小于8值等于8的要素就被漏掉了。排查方法就是用WFS把要素的真实数值拉出来跟每条Rule的Filter条件对照。看漏值到底落在哪个区间然后手动修改SLD里的比较符。需要改的时候注意PropertyIsGreaterThanOrEqualTo和PropertyIsLessThan这类的组合关系改完重新验证和预览。还有一个精度问题是数据更新场景特有的如果MXD里的分级阈值是表达式计算出来的转换后SLD只固化了计算结果以后源数据更新了分级边界不会自动跟着变。这种情况要回到ArcMap里重新调整阈值再重新转换导出SLD。5.4 坐标系和图层绘制顺序坐标系问题在GeoServer非常常见。发布图层时如果Native SRS识别不了必须手动填。填错之后最典型的表现是预览时图层空白或者跑到地图角落。正确流程是先确认数据本身的坐标系再在发布页面正确声明然后点从数据的边界框计算最后预览。Web前端通常用的坐标系是EPSG:3857Web墨卡托或EPSG:4326经纬度。GeoServer的WMS服务支持自动重投影只要SRS声明正确无需手动转换数据它会自动完成从原始坐标系到输出坐标系的转换。但要注意的是SLD里的比例尺分母MinScaleDenominator/MaxScaleDenominator在不同坐标系下对应的显示级别不一样同一个SLD在EPSG:4326和EPSG:3857下预览显示的缩放范围可能不同。图层绘制顺序也值得注意。ArcMap的图层顺序是TOC列表里的上下关系转换工具按TOC顺序输出Rule或者FeatureTypeStyle时如果顺序乱了就出现面盖住线、线盖住点的情况。多图层导出的SLD要检查FeatureTypeStyle的先后顺序通常应该先面、再线、最后点跟绘图常识一致。如果转换工具输出的顺序不对在SLD里手动调整FeatureTypeStyle节点位置或者调整Rule的先后顺序即可。GeoServer渲染时按照SLD里出现的顺序依次绘制前面的会被后面的盖住所以顺序处理不好站点符号可能在道路下面看不见。最后的几句闲话这套流程跑下来我的体会是arcmap2SLD是个好帮手但它不是万能的。它能把常规专题图省掉90%的手写SLD工作量但复杂符号系统始终需要人工收尾。我建议把数据发布和样式转换拆开验证先确认数据在GeoServer里显示正常再挂样式然后一层层排查。转换出来的SLD当作一个半成品到了GeoServer里再根据Web端实际效果微调这样效率最高。另外一个小技巧每次在ArcMap里改了MXD样式之后重新导出SLD前把旧文件备份一下。新样式出了问题还能快速对比回滚。这个习惯帮我节省了很多时间也推荐给你。
返回列表