如何使用java解析OpenStreetMap官网导出的OSM文件数据

 官网:https://www.openstreetmap.org/

1、导出按钮

2、手动选择区域

3、导出文件为osm,举例结构为

<osm version="0.6" generator="Overpass API">
  <node id="1" lat="52.51631" lon="13.37777">
    <tag k="amenity" v="restaurant"/>
  </node>
  <node id="2" lat="52.51629" lon="13.37827"/>
  <node id="3" lat="52.51620" lon="13.37829"/>
  <way id="1">
    <nd ref="2"/>
    <nd ref="3"/>
    <tag k="highway" v="residential"/>
  </way>
  <relation id="1" visible="true" version="6" changeset="147492225" timestamp="2024-02-15T13:40:43Z" user="hdThomas" uid="9010216">
  <member type="relation" ref="2" role=""/>
  <member type="relation" ref="3" role=""/>
  <tag k="name" v="test"/>
  <tag k="network" v="hello"/>
</relation>
</osm>

4、如何通过java去进行解析

package com.jcl.birthdaydemo;

import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.jcl.birthdaydemo.entity.Book;
import com.jcl.birthdaydemo.entity.Category;
import com.jcl.birthdaydemo.entity.OrgPointGeo;
import com.jcl.birthdaydemo.service.IBookService;
import com.jcl.birthdaydemo.service.ICategoryService;
import com.jcl.birthdaydemo.service.service.IOrgPointGeoService;
import org.apache.commons.lang3.ObjectUtils;
import org.jsoup.Jsoup;
import org.jsoup.select.Elements;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;


/**
 * 节点(Nodes):
 * <p>
 * 节点是 OSM 数据的基本单位,代表地图上的一个具体点。每个节点都有一个唯一的 ID 和一对经纬度坐标。
 * 节点可以表示独立的地理要素,如路标、树木、邮筒等,也可以是更复杂要素(如道路、建筑物)的组成部分。
 * 路径(Ways):
 * <p>
 * 路径是由多个节点按顺序连接而成的线性要素,可以表示道路、河流、边界等。
 * 闭合的路径(首尾节点相同)通常表示面状要素,如建筑物、湖泊、公园等。
 * 关系(Relations):
 * <p>
 * 关系用于表示更复杂的地理要素或多个要素之间的关系。一个关系可以包含多个节点和路径,并定义它们之间的关系。
 * 例如,关系可以表示公交线路(由多个路径组成)或多边形(由多个路径组成的复杂区域)。
 * 标签(Tags):
 * <p>
 * 每个节点、路径和关系都可以有若干标签,用于描述它们的属性。标签由键值对组成,例如 highway=residential 表示住宅区道路,building=yes 表示建筑物。
 */
@SpringBootTest
public class OSM {

    private final static String path = "C:\\Users\\lin\\Desktop\\test.osm";

    @Autowired
    private IOrgPointGeoService pointGeoService;

    @Test
    void main() throws JsonProcessingException {
        System.out.println("开始解析OSM文件...");
        function4End();
    }

    public void function4End() {
        try {
            // 1. 解析XML文件
            File inputFile = new File(path);
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            org.w3c.dom.Document doc = builder.parse(inputFile);
            // 2. 解析并写入node信息
            writeNodesToFile(doc);

            // 3. 解析并写入way信息
            writeWaysToFile(doc);
//
//            // 4. 解析并写入relation信息
            writeRelationsToFile(doc);

            System.out.println("OSM文件解析完成,生成了node.txt、way.txt和relation.txt文件。");

        } catch (ParserConfigurationException | SAXException | IOException e) {
            e.printStackTrace();
        }
    }

    // 解析并写入node信息
    public void writeNodesToFile(org.w3c.dom.Document doc) throws IOException {
        FileWriter writer = new FileWriter("node-test.txt");
        FileWriter writer2 = new FileWriter("node-test-sql.txt");
        NodeList nodes = doc.getElementsByTagName("node");
        for (int i = 0; i < nodes.getLength(); i++) {
            org.w3c.dom.Element node = (org.w3c.dom.Element) nodes.item(i);
            String nodeId = node.getAttribute("id");
            String lat = node.getAttribute("lat");
            String lon = node.getAttribute("lon");
            writer.write("Node id: " + nodeId + ", lat: " + lat + ", lon: " + lon + "\n");

            String nodeSql = "INSERT INTO `bodf1`.`org_point_geo`( `lat`, `lng`, `nid`) VALUES ( " + lat + ", " + lon + ", " + nodeId + ");\n";


            writer2.write(nodeSql + "\n");

            // 获取节点的标签(tags)
            NodeList tags = node.getElementsByTagName("tag");
            for (int j = 0; j < tags.getLength(); j++) {
                org.w3c.dom.Element tag = (org.w3c.dom.Element) tags.item(j);
                String key = tag.getAttribute("k");
                String value = tag.getAttribute("v");
                writer.write("  Tag key: " + key + ", value: " + value + "\n");
            }
        }
        writer.close();
        writer2.close();
    }

    // 解析并写入way信息
    public void writeWaysToFile(org.w3c.dom.Document doc) throws IOException {

        FileWriter writer = new FileWriter("way-test.txt");
        FileWriter writerSql = new FileWriter("way-test-sql.txt");
        FileWriter writerSql2 = new FileWriter("way-test2.txt");
        NodeList ways = doc.getElementsByTagName("way");
        for (int i = 0; i < ways.getLength(); i++) {
            String title = null;
            String bpoint = null;
            String epoint = null;
            boolean type = true;
            StringBuilder lineInfo = new StringBuilder();
            org.w3c.dom.Element way = (org.w3c.dom.Element) ways.item(i);
            String wayId = way.getAttribute("id");

            writer.write("Way id: " + wayId + "\n");

            // 获取way的子节点(nd)
            NodeList nds = way.getElementsByTagName("nd");
            lineInfo.append("[");
            for (int j = 0; j < nds.getLength(); j++) {
                org.w3c.dom.Element nd = (org.w3c.dom.Element) nds.item(j);
                String ref = nd.getAttribute("ref");
//                writer.write("  Nd ref: " + ref + "\n");
                LambdaQueryWrapper<OrgPointGeo> queryWrapper = new LambdaQueryWrapper<>();
                OrgPointGeo pointGeoServiceOne = pointGeoService.getOne(queryWrapper.eq(OrgPointGeo::getNid, ref));
                if (j == 0) {
                    bpoint = pointGeoServiceOne.getLng() + "," + pointGeoServiceOne.getLat();
                } else if (j == nds.getLength() - 1) {
                    epoint = pointGeoServiceOne.getLng() + "," + pointGeoServiceOne.getLat();
                    lineInfo.append("[" + pointGeoServiceOne.getLng() + "," + pointGeoServiceOne.getLat() + "]");
                } else {
                    lineInfo.append("[" + pointGeoServiceOne.getLng() + "," + pointGeoServiceOne.getLat() + "],");
                }

            }
            lineInfo.append("]");
            // 获取way的标签(tags)
            NodeList tags = way.getElementsByTagName("tag");
            for (int j = 0; j < tags.getLength(); j++) {
                org.w3c.dom.Element tag = (org.w3c.dom.Element) tags.item(j);
                String key = tag.getAttribute("k");
                String value = tag.getAttribute("v");
                writer.write(
                        "  Tag key: " + key + ", value: " + value + "\n");
                if(key.equals("name")){
                    title = value;
                }
                switch (key) {
                    case "highway":
                        type = true;
                        break;
                    case "landuse":
                    case "building":
                    case "leisure":
                    case "amenity":
                        type = false;
                        break;
                    default:
                        break;
                }
            }
            String waySql;
            writerSql2.write("wayId:"+wayId +   "  type:"+type+   "  title:"+title+   "  bpoint:"+bpoint+   "  epoint:"+epoint +   "  lineInfo:"+lineInfo + "\n");
            if (type) {
                waySql = "INSERT INTO `bodf1`.`org_ways`( `title`, `bpoint`, `epoint`, `weight`, `lineInfo`) " +
                        "VALUES ( '" + title + "', '" + bpoint + "', '" + epoint + "', '0.0', '" + lineInfo + "');\n";
            } else {
                waySql = "INSERT INTO `bodf1`.`org_buildings`( `title`, `bpoint`, `epoint`, `weight`, `lineInfo`) " +
                        "VALUES ( '" + title + "', '" + bpoint + "', '" + epoint + "', '0.0', '" + lineInfo + "');\n";
            }
            writerSql.write(waySql);
        }
        writer.close();
        writerSql.close();
        writerSql2.close();
    }

    // 解析并写入relation信息
    public void writeRelationsToFile(Document doc) throws IOException {
        FileWriter writer = new FileWriter("relation-test.txt");
        NodeList relations = doc.getElementsByTagName("relation");
        for (int i = 0; i < relations.getLength(); i++) {
            org.w3c.dom.Element relation = (org.w3c.dom.Element) relations.item(i);
            String relationId = relation.getAttribute("id");
            String visible = relation.getAttribute("visible");
            String version = relation.getAttribute("version");
            String changeset = relation.getAttribute("changeset");
            String timestamp = relation.getAttribute("timestamp");
            String user = relation.getAttribute("user");
            String uid = relation.getAttribute("uid");

            writer.write("Relation id: " + relationId + ", visible: " + visible + ", version: " + version +
                    ", changeset: " + changeset + ", timestamp: " + timestamp + ", user: " + user + ", uid: " + uid + "\n");

            // 获取relation的成员(members)
            NodeList members = relation.getElementsByTagName("member");
            for (int j = 0; j < members.getLength(); j++) {
                org.w3c.dom.Element member = (org.w3c.dom.Element) members.item(j);
                String type = member.getAttribute("type");
                String ref = member.getAttribute("ref");
                String role = member.getAttribute("role");
                writer.write("  Member type: " + type + ", ref: " + ref + ", role: " + role + "\n");
            }

            // 获取relation的标签(tags)
            NodeList tags = relation.getElementsByTagName("tag");
            for (int j = 0; j < tags.getLength(); j++) {
                org.w3c.dom.Element tag = (Element) tags.item(j);
                String key = tag.getAttribute("k");
                String value = tag.getAttribute("v");
                writer.write("  Tag key: " + key + ", value: " + value + "\n");
            }
        }
        writer.close();

    }

}


5、数据库表结构sql

CREATE TABLE `org_ways` (
  `id` int NOT NULL AUTO_INCREMENT,
  `title` varchar(50) DEFAULT NULL COMMENT '名称',
  `bpoint` varchar(50) DEFAULT NULL COMMENT '起始',
  `epoint` varchar(50) DEFAULT NULL COMMENT '结束',
  `weight` varchar(50) DEFAULT NULL COMMENT '权重',
  `lineInfo` varchar(6000) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '路线',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=939 DEFAULT CHARSET=utf8mb3;

CREATE TABLE `org_buildings` (
  `id` int NOT NULL AUTO_INCREMENT,
  `title` varchar(50) DEFAULT NULL COMMENT '名称',
  `bpoint` varchar(50) DEFAULT NULL COMMENT '起始',
  `epoint` varchar(50) DEFAULT NULL COMMENT '结束',
  `weight` varchar(50) DEFAULT NULL COMMENT '权重',
  `lineInfo` varchar(6000) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '路线',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=827 DEFAULT CHARSET=utf8mb3 COMMENT='建筑物信息';

CREATE TABLE `org_point_geo` (
  `id` int NOT NULL AUTO_INCREMENT,
  `lat` double DEFAULT NULL COMMENT '经度',
  `lng` double DEFAULT NULL COMMENT '纬度',
  `nid` varchar(299) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1437 DEFAULT CHARSET=utf8mb3;

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值