基于JavaAPIforKml实现Kml 2.2版本的全量解析实践-以两步路网站为例

目录

前言

一、关于两步路网站

1、相关功能

2、数据结构介绍

二、JAK的集成与实现

1、JAK类图简介

2、解析最外层数据

3、解析扩展元数据和样式

4、递归循环解析Feature

5、解析具体的数据

三、结论


前言

        随着地理信息技术的快速发展,地理空间数据的共享和可视化已成为现代信息技术的重要组成部分。KML(Keyhole Markup Language)作为一种基于XML的标记语言,因其简单易用、结构清晰以及与Google Earth等地理信息平台的无缝集成,已成为地理空间数据交换和展示的标准格式之一。KML 2.2版本作为其最新规范,不仅保留了早期版本的核心功能,还引入了更多复杂地理数据的表达能力,如三维模型、时间序列、网络链接等,为地理信息的多样化展示提供了强有力的支持。然而,KML文件的复杂性也给数据解析带来了挑战。一个典型的KML文件可能包含嵌套的地理对象、样式定义、扩展字段以及动态数据链接,这些内容的解析需要对KML规范有深入的理解,并结合高效的解析工具。Java API for KML(JAK)作为一款开源的KML解析和生成工具,提供了对KML 2.2版本的全面支持,能够自动解析KML文件的结构,提取地理数据,并将其转换为Java对象,从而简化了KML数据的处理流程。

        本文以“两步路”网站为例,探讨基于Java API for KML实现KML 2.2版本全量解析的实践方法。两步路网站作为一个专注于户外路线分享的平台,用户上传的路线数据通常以KML格式存储,这些数据包含了丰富的地理信息,如路径点、轨迹、地标、样式等。通过解析这些KML文件,不仅可以实现路线数据的可视化展示,还能进一步挖掘数据中的潜在价值,为用户提供更多个性化的服务。在实践中,我们首先介绍了KML 2.2版本的核心特性和Java API for KML的基本功能,然后详细阐述了如何利用JAK实现KML文件的全量解析。通过代码示例和实际案例,展示了如何提取KML文件中的地理对象、样式信息以及扩展字段,并将其转换为Java对象进行后续处理。此外,我们还探讨了解析过程中可能遇到的常见问题及其解决方案,如嵌套结构的处理、动态数据的解析以及性能优化等。

        本文的目标是为地理信息开发者提供一个基于Java API for KML的完整解析方案,帮助大家更高效地处理KML 2.2版本的复杂数据。通过结合两步路网站的实际应用场景,我们不仅验证了JAK在解析KML文件方面的有效性和灵活性,还展示了其在实际项目中的应用潜力。希望本文的实践经验和方法能够为相关领域的开发者提供参考和借鉴,推动KML技术在地理信息领域的进一步应用和发展。

一、关于两步路网站

        深圳市两步路信息技术有限公司是一家专注于位置定位服务(LBS)及其周边应用的科技企业,其打造的"两步路"平台是全国领先的专业户外平台,旗下产品有两步路户外助手APP两步路户外网。多年来,两步路始终以“探索新世界,安全户外行”的理念服务广大户外爱好者,曾举办、协办的大型活动有:第三届中国百色山地户外挑战赛、首届全国攀岩精英赛、全能五仕挑战赛、为爱健行徒步大会、北回归线上的足迹、红牛24小时越野系列赛等......

        两步路户外网是一个户外资源共享和社区互动网站。在这里,您可以参加精彩户外活动;搜索海量户外轨迹路线;购买精选户外专业装备;加入热门户外互动社区,组建周边户外圈子。两步路户外网是您户外出行贴心、专业的好伙伴。

        传送门:两步路官网。 感兴趣的大家可以到系统上进行体验。

1、相关功能

        网站提供以下的功能,

  • 行前

  •  搜索线路搜索轨迹线路,下载离线地图,为出行作规划导航。

  • 约伴出行: 寻找线路活动,你也可以自己发布活动约伴出行;

    购买装备在户外商城购置专业实惠的户外装备和周全贴心的户外保险;

  • 行中

  • 标注轨迹记录出行线路轨迹,用文字、语音、图片、视频标注轨迹点;

    组队定位若组队出行,有网络的情况下,队员之间可通过网络进行位置共享及互动,无网络的情况下,也可通过行影手麦组队,实现即时语音沟通和GPS定位;

    安全救援如遭遇突发情况,可触发紧急呼救,召附近集户外救援队伍;

  • 行后

  • 总结点评您可以点评此次活动质量,点评户外装备性能;

    轨迹备份整理出行期间所有的轨迹,整理备份,上传至云端;

    社区分享制作攻略游记,发表心得体会,在社区中与驴友互动分享;

        以上功能列表来源于官方网站,个人觉得这个网站做的非常不错,满足了我们爬山运动的需求,同时带有较强的社交属性。其中包含的轨迹信息非常值得研究。我们可以切换城市后,查看家或者工作地点附近的轨迹信息,界面如下:

        在这里可以看到很详细的该条路线的所有信息。 如果感兴趣的大家可以在网站上注册成为会员,然后就可以根据需要将这条行动轨迹进行下载到本地进行分享,同时可以对应的位置的定位。

2、数据结构介绍

        这里以长沙市岳麓山的某一条行动路线为例,使用注册好账号登录到系统中,然后下载KML格式的数据,在本地的文件信息格式如下:

        通过右边的XML层次结构可以看到,这份KML数据包含的节点主要包含name、description、author,以及 ExtendedData、n个style样式对象和n个 Folder对象。在Folder对象就中包含了详细的位置和时序信息。

二、JAK的集成与实现

        在了解了这个KML文件的相关结构之后,我们就可以使用JAK组件来进行数据的解析。本节将从JAK的相关类、JAK的实际处理以及JAK的解析成果出发,详细介绍如何使用JAK来进行相应数据的解析。

1、JAK类图简介

        首先依然来介绍一下JAK的相关类,在之前的博客中我们也曾经对JAK组件进行了简单的介绍。纯Java实现Google地图的KMZ和KML文件的解析。原来的KML数据比较简单,因此没有深入的介绍。由于本文涉及完整解析,因此有必要对JAK的相关类进行简单介绍,让大家学习起来更加轻松。首先来看一下类图:

        通过类图可以看到,其实解析的组件就是解析XML,然后去转换成对应的JavaBean的。这是基本的原理介绍。为了简单示例,这里仅介绍有所涉及的主要类,其它的一些辅助类或者父类不在此进行详细描述。主要用的是一个Document类、Feature类、Kml类、ExtendedData类、StyleSelector类和Geometry类。在后续的解析中还有一个很重要的Placemark类。在这份轨迹数据中,其中有大量的重复子类进行展示,因此要求我们对这些子类信息非常熟悉,在繁杂的数据挖掘和展示中不会出错。

2、解析最外层数据

        在了解了相关后台的类之后,我们来看一下实际如何解析这些数据。根据KML文档的结构,首先我们可以解析最外层的元数据信息,代码如下:

// 解析 KML 文件
Kml kml = Kml.unmarshal(kmlFile);
Feature feature = kml.getFeature();
System.out.println("step1、解析基本信息");
System.out.println("获取基本信息 start......");
System.out.println(feature.getDescription());
System.out.println(feature.getName());
System.out.println(feature.getSnippetd());
System.out.println("获取基本信息 end ......");

        程序运行后获取的信息如下:

step1、解析基本信息
获取基本信息 start......
岳麓山“爱心线”徒步
通过“两步路”生成,http://www.2bulu.com
获取基本信息 end ......

3、解析扩展元数据和样式

        解析扩展元数据和样式信息的关键代码如下:

System.out.println("step2、解析扩展信息 start......");
ExtendedData extendedData = feature.getExtendedData();List<Data> dataList = extendedData.getData();
for (Data data : dataList) {System.out.println(data.getName() + "\t" + data.getValue());
}
System.out.println("step2、解析扩展信息 end......");
List<SchemaData> schemaDataList = extendedData.getSchemaData();
for(SchemaData data : schemaDataList) {System.out.println(data.getTargetId() + "\t" + data.getSchemaUrl());
}
System.out.println("**************************************");List<StyleSelector> styleSelectorList = feature.getStyleSelector();
for(StyleSelector style : styleSelectorList) {System.out.println(style.getId() + style.getObjectSimpleExtension());
}

        程序运行后获得的信息如下:

   4、递归循环解析Feature

        递归循环解析Feature的关键代码如下:

 private static void printFeature(Feature feature) {if (feature != null) {// 获取第一层节点List<Feature> firstLayerNodes = getFirstLayerNodes(feature);// 遍历第一层节点并打印其值for (Feature node : firstLayerNodes) {System.out.println(node.getName()+ "\t start");printNodeValues(node);ExtendedData extendedData = node.getExtendedData();if(null != extendedData) {List<Data> dataList = extendedData.getData();for (Data data : dataList) {System.out.println(data.getName() + "\t" + data.getValue());}}printFeature(node);System.out.println(node.getName()+ "\t end");}}
}

        运行后的结果如下:

 5、解析具体的数据

         解析具体数据的代码如下:

private static void printNodeValues(Feature feature) {if (feature instanceof Placemark) {Placemark placemark = (Placemark) feature;System.out.println("Placemark Name: " + placemark.getName());System.out.println("Placemark Description: " + placemark.getDescription());Geometry geometry = placemark.getGeometry();TimePrimitive time = placemark.getTimePrimitive();//step1、解析时间if(time instanceof TimeStamp) {TimeStamp timeStamp = (TimeStamp)time;System.out.println("时间===>"+timeStamp.getWhen());}//step2、解析空间数据if (geometry instanceof Point) {Point point = (Point) geometry;System.out.println("海拔高度:" + point.getCoordinates().get(0).getAltitude());System.out.println("Point Coordinates: " + point.getCoordinates());} else if (geometry instanceof LineString) {LineString lineString = (LineString) geometry;System.out.println("LineString Coordinates: " + lineString.getCoordinates());} else if (geometry instanceof Polygon) {Polygon polygon = (Polygon) geometry;System.out.println("Polygon Coordinates: " + polygon.getOuterBoundaryIs().getLinearRing().getCoordinates());}// step3、解析track信息if(geometry instanceof Track) {Track track = (Track)geometry;List<String> coordList = track.getCoord();System.out.println(coordList);List<Data> dataList = track.getExtendedData().getData();for (Data data : dataList) {System.out.println(data.getName() + "\t" + data.getValue());}List<String> when =  track.getWhen();System.out.println(when);}} else if (feature instanceof Document) {Document document = (Document) feature;System.out.println("Document Name: " + document.getName());System.out.println("Document Description: " + document.getDescription());} else if (feature instanceof Folder) {Folder folder = (Folder) feature;System.out.println("Folder Name: " + folder.getName());System.out.println("Folder Description: " + folder.getDescription());}}

        这里不仅仅实现对空间数据的解析,同时实现了对时序中的时序的采集。这些数据在后期对于数据分析作用很大。程序运行后的效果如下:

        至此,完成的KML完整解析提取就实现完毕。 

三、结论

        以上就是本文的主要内容,本文以“两步路”网站为例,探讨基于Java API for KML实现KML 2.2版本全量解析的实践方法。本文的目标是为地理信息开发者提供一个基于Java API for KML的完整解析方案,帮助大家更高效地处理KML 2.2版本的复杂数据。通过结合两步路网站的实际应用场景,我们不仅验证了JAK在解析KML文件方面的有效性和灵活性,还展示了其在实际项目中的应用潜力。希望本文的实践经验和方法能够为相关领域的开发者提供参考和借鉴,推动KML技术在地理信息领域的进一步应用和发展。行文仓促,定有不足之处,欢迎各位朋友在评论区批评指正,不胜感激。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/75380.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

脑科学与人工智能的交叉:未来智能科技的前沿与机遇

引言 随着科技的迅猛发展&#xff0c;脑科学与人工智能&#xff08;AI&#xff09;这两个看似独立的领域正在发生深刻的交汇。脑机接口、神经网络模型、智能机器人等前沿技术&#xff0c;正带来一场跨学科的革命。这种结合不仅推动了科技进步&#xff0c;也在医疗、教育、娱乐等…

3.1.3.2 Spring Boot使用Servlet组件

在Spring Boot应用中使用Servlet组件&#xff0c;可以通过注解和配置类两种方式注册Servlet。首先&#xff0c;通过WebServlet注解直接在Servlet类上定义URL模式&#xff0c;Spring Boot会自动注册该Servlet。其次&#xff0c;通过创建配置类&#xff0c;使用ServletRegistrati…

《AI大模型应知应会100篇》第10篇:大模型的涌现能力:为什么规模如此重要

第10篇&#xff1a;大模型的涌现能力&#xff1a;为什么规模如此重要 摘要 在人工智能领域&#xff0c;“规模"始终是大模型发展的核心关键词。随着参数量从百万级跃升至万亿级&#xff0c;大模型展现出令人惊叹的"涌现能力”&#xff1a;这些能力在小模型中几乎不可…

安宝特案例 | Fundació Puigvert 医院应用AR技术开创尿石症治疗新纪元

案例介绍 在医疗科技不断进步的今天&#xff0c;Fundaci Puigvert 医院迈出了重要一步&#xff0c;成功应用AR技术进行了全球首例同时使用两台内窥镜的ECIRS手术&#xff08;内镜肾内联合手术&#xff09;&#xff0c;由Esteban Emiliani M.D. PhD F.E.B.U 博士主刀。这标志着…

从数据海洋中“淘金”——数据挖掘的魔法与实践

从数据海洋中“淘金”——数据挖掘的魔法与实践 在这个数据飞速膨胀的时代&#xff0c;每天产生的数据量可以用“天文数字”来形容。如果将数据比作金矿&#xff0c;那么数据挖掘&#xff08;Data Mining&#xff09;就是在数据的海洋中挖掘黄金的技术。作为一门结合统计学、机…

kotlin的takeIf使用

takeIf用于判断指定对象是否满足条件&#xff0c;满足就返回该对象自身&#xff0c;不满足返回null。因为可以返回对象自身&#xff0c;所以可以用作链式调用&#xff0c;以简化代码&#xff0c;又因takeIf可能返回空&#xff0c;所以常常和let结合使用&#xff0c;示例如下&am…

[定位器]晶艺LA1823,4.5V~100V, 3.5A,替换MP9487,MP9486A,启烨科技

Features  4.5V to 100V Wide Input Range  3.5A Typical Peak Current Limit  Integrated 500mΩ low resistance high side power MOS.  Constant On Time Control with Constant Switching Frequency.  180μA Low Quiescent Current  150kHz/240kHz/420kHz Swi…

火山RTC 4 音视频引擎 IRTCVideo,及 音视频引擎事件回调接口 IRTCVideoEventHandler

一、IRTCVideo、IRTCVideoEventHandler 音视频引擎 IRTCVideo&#xff0c;及 音视频引擎事件回调接口 IRTCVideoEventHandler 负责音视频管理、创建房间/获得房间实例 1、创建引擎、及事件回调示例 如&#xff1a; void VideoConfigWidget::initRTCVideo() {m_handler.res…

前端获取不到后端新加的字段 解决方案

前端获取不到后端新加的字段 解决方案 sql 返回的是 FileInfo 对象 private String lastUpdateTimeStr;// 自定义 setLastUpdateTime 方法&#xff0c;确保在设置 lastUpdateTime 时自动格式化为字符串public void setLastUpdateTime(LocalDateTime lastUpdateTime) {this.las…

30天学Java第九天——线程

并行与并发的区别 并行是多核 CPU 上的多任务处理&#xff0c;多个任务在同一时间真正的同时执行并发是单核 CPU 上的多任务处理&#xff0c;多个任务在同一时间段内交替执行&#xff0c;通过时间片轮转实现交替执行&#xff0c;用于解决 IO 密集型任务的瓶颈 线程的创建方式…

论坛系统(测试报告)

文章目录 一、项目介绍二、设计测试用例三、自动化测试用例的部分展示用户名或密码错误登录成功编辑自己的帖子成功修改个人信息成功回复帖子信息成功 四、性能测试总结 一、项目介绍 本平台是用Java开发&#xff0c;基于SpringBoot、SpringMVC、MyBatis框架搭建的小型论坛系统…

智膳优选 | AI赋能的智慧食堂管理专家 —— 基于飞书多维表格和扣子(Coze)的智能解决方案

智膳优选 | AI赋能的智慧食堂管理专家 基于飞书多维表格和扣子&#xff08;Coze&#xff09;的智能解决方案 数据驱动餐饮管理&#xff0c;让每一餐都是营养与经济的完美平衡&#xff01; “智膳优选”通过整合飞书与Coze&#xff0c;将数据智能引入校园餐饮管理&#xff0…

练习(含指针数组与数组指针的学习)

数组指针是一个指向数组的指针&#xff0c;而指针数组是一个存储指针的数组。 ‌数组指针‌&#xff1a;是一个指针&#xff0c;指向一个数组的首地址&#xff0c;它用于指向整个数组&#xff0c;而不是数组中的某个元素。例如&#xff0c;int (*p)表示 p 是一个指向包含 5 个整…

NSS#Round30 Web

小桃的PHP挑战 <?php include jeer.php; highlight_file(__FILE__); error_reporting(0); $A 0; $B 0; $C 0;//第一关 if (isset($_GET[one])){$str $_GET[str] ?? 0;$add substr($str, 0, 1); $add;if (strlen($add) > 1 ) {$A 1;} else {echo $one; } } else…

MCP基础学习二:MCP服务搭建与配置

文章目录 MCP服务搭建与配置一&#xff0c;学习目标&#xff1a;二&#xff0c;学习内容&#xff1a;1. 如何搭建MCP服务端服务端初始化与配置MCP服务架构与数据流交互图核心实现注册服务功能服务器启动与API暴露 2. 本地应用与MCP服务的集成客户端SDK实现客户端应用实现功能演…

ZKmall开源商城服务端验证:Jakarta Validation 详解

ZKmall开源商城基于Spring Boot 3构建&#xff0c;其服务端数据验证采用Jakarta Validation API​&#xff08;原JSR 380规范&#xff09;&#xff0c;通过声明式注解与自定义扩展机制实现高效、灵活的数据校验体系。以下从技术实现、核心能力、场景优化三个维度展开解析&#…

使用Docker创建postgres

准备工作&#xff1a; 1. 检查网络 检查网络连接&#xff1a;确保你的服务器网络连接正常&#xff0c;可尝试使用 ping 命令测试与 Docker Hub 服务器&#xff08;如 ping registry-1.docker.io&#xff09;的连通性。 ping registry-1.docker.io 检查防火墙&#xff1a;确…

32 python json

在办公室忙碌的日常里,我们经常需要和各种数据打交道。想象一下,你是办公室里负责处理员工信息、项目数据的 “数据小管家”,每天都要面对大量格式各异的数据。 这时候,JSON(JavaScript Object Notation)就像是你得力的数据助手,它是一种轻量级的数据交换格式,简单又高…

Java 实现 List<String> 与 String 互转

在 Java 开发过程中&#xff0c;有时需要将 List<String> 转为 String 存储&#xff0c;后续使用时再还原回去。此时就需要 Java 实现 List<String> 与 String 互转。以下是一种互转方式。 采用如下工具包实现。 <dependency><groupId>org.apache.com…

NO.87十六届蓝桥杯备战|动态规划-完全背包|疯狂的采药|Buying Hay|纪念品(C++)

完全背包 先解决第⼀问 状态表⽰&#xff1a; dp[i][j]表⽰&#xff1a;从前i个物品中挑选&#xff0c;总体积不超过j&#xff0c;所有的选法中&#xff0c;能挑选出来的最⼤价 值。&#xff08;这⾥是和01背包⼀样哒&#xff09; 那我们的最终结果就是dp[n][V] 。状态转移⽅…