moonkml

    纯 MoonBit 的 KML/KMZ 读写库:文档模型、XML 解析、点/线/面几何与样式

    kml
    kmz
    gis
    xml
    geospatial
    google-earth
    Download zip
    Version
    0.1.0
    License
    Apache-2.0
    Last updated
    1 hour ago
    Downloads
    4

    #moonkml

    纯 MoonBit 实现的 KML 2.2 读写库。零 FFI,可运行在 wasm-gc、js 与 native 后端。

    KML 是 Google Earth、无人机航迹、GPS 轨迹与地图标注的通用交换格式;KMZ 是它的 ZIP 封装。MoonBit 生态已有 shapefile、GeoJSON、WKT/WKB、GPX、TopoJSON、MVT 等 GIS 模块,KML/KMZ 此前一直是空缺。

    #安装

    moon add cp15695540483/moonkml

    在 moon.pkg 中导入:

    import { "cp15695540483/moonkml" @kml, }

    #能力

    能力状态
    KML 解析(XML 子集:元素、属性、文本、CDATA、注释、PI、实体引用)✅
    几何:Point / LineString / Polygon(外环 + 内环)/ MultiGeometry✅
    Placemark name / description / styleUrl✅
    Style(LineStyle 颜色与宽度、PolyStyle 颜色)✅
    ExtendedData(Data name/value)✅
    KML 序列化(模型 → KML 文本)✅
    KMZ 读写(ZIP + DEFLATE 解压 + CRC32 校验)✅
    导出 GeoJSON(RFC 7946)与 GPX 1.1✅
    命令行:摘要 / GeoJSON / GPX 输出✅
    Camera / LookAt / 时间戳 / 网络链接未实现(明确不做)

    #使用

    #解析 KML 文本

    let doc = try! @kml.parse(kml_text)
    println(doc.name)
    for pm in doc.placemarks {
    match pm.geometry {
    Some(@kml.Geometry::Point(p)) => println(pm.name + ": " + p.lon.to_string() + ", " + p.lat.to_string())
    Some(@kml.Geometry::LineString(ls)) => println(pm.name + ": " + ls.point_count().to_string() + " vertices")
    Some(@kml.Geometry::Polygon(poly)) => println(pm.name + ": " + poly.inner_count().to_string() + " holes")
    Some(@kml.Geometry::MultiGeometry(gs)) => println(pm.name + ": " + gs.length().to_string() + " parts")
    None => println(pm.name + ": no geometry")
    }
    }

    #读写 KMZ

    let doc = try! @kml.kmz_parse(kmz_bytes) // 支持 DEFLATE 压缩的标准 KMZ
    let bytes = @kml.kmz_pack(doc) // 打包为 KMZ

    #导出

    let geojson = @kml.to_geojson(doc)
    let gpx = @kml.to_gpx(doc)
    let kml_text = @kml.serialize(doc)

    #命令行

    moon run cmd/main -- examples/sample.kml --summary moon run cmd/main -- examples/sample.kml --geojson moon run cmd/main -- examples/sample.kml --gpx

    #API 摘要

    • parse(text : String) -> KmlDocument raise KmlError
    • serialize(doc : KmlDocument) -> String
    • kmz_parse(data : Bytes) -> KmlDocument raise KmlError / kmz_pack(doc) -> Bytes
    • to_geojson(doc) -> String / to_gpx(doc) -> String
    • parse_xml(text) -> XmlElement raise KmlError(通用 XML 子集)
    • KmlDocument::{ name, placemarks, styles, placemark_count(), style_count(), find_style(id) }
    • Placemark::{ name, description, geometry, style_url, extended_data, has_geometry(), has_point(), has_line_string(), has_multi_geometry(), data_count(), find_data(name) }
    • Geometry::{ Point(KmlPoint), LineString(KmlLineString), Polygon(KmlPolygon), MultiGeometry(Array[Geometry]) }
    • KmlPolygon::{ outer, inner, inner_count() }、KmlStyle::{ id, line_color, line_width, fill_color }

    #设计说明

    • XML 子集:KML 只需要元素、属性、文本、CDATA、注释、处理指令与常见实体引用;不实现 DTD 实体展开与命名空间解析,未知元素直接忽略(KML 允许扩展元素)。
    • 错误模型:KmlError 区分 XML 结构错误(带字节偏移)、KML 语义错误(缺 coordinates、坐标非法)与宿主 I/O 错误,便于调用方给出可定位的报错。
    • 坐标解析:单次除法/乘法做十进制定标,避免逐位缩放带来的多次舍入;测试用 1e-9 容差断言。
    • ZIP 策略:读取支持 Stored 与 DEFLATE(DEFLATE 解压复用 moonbit-community/flate,纯 MoonBit);写入使用 DEFLATE + CRC32。

    #构建与测试

    moon check --target wasm-gc --deny-warn moon test --target wasm-gc moon test --target js moon fmt --check

    #许可证

    Apache-2.0,见 LICENSE。

    #参考

    • OGC KML 2.2 标准
    • RFC 7946(GeoJSON)、GPX 1.1 Schema
    • moonbit-community/flate(DEFLATE 引擎,Apache-2.0)

    KmlError

    pub(all) suberror KmlError {
    XmlSyntax(String, Int)
    XmlMismatch(String, String, Int)
    XmlUnexpectedEnd(String, Int)
    XmlUnclosed(String, Int)
    XmlMissingRoot
    XmlMultipleRoots(Int)
    MissingCoordinates
    BadCoordinates(String)
    HostIo(String)
    }

    Geometry

    pub(all) enum Geometry {
    Point(KmlPoint)
    LineString(KmlLineString)
    Polygon(KmlPolygon)
    MultiGeometry(Array[Geometry])
    }

    几何类型。

    KmlData

    pub(all) struct KmlData {
    name : String
    value : String
    }

    一个扩展数据条目(..)。

    KmlDocument

    pub(all) struct KmlDocument {
    name : String
    placemarks : Array[Placemark]
    styles : Array[KmlStyle]
    }

    样式表:id → 样式定义。

    KmlDocument::find_style

    fn KmlDocument::find_style(self : KmlDocument, id : String) -> KmlStyle?

    按 id 找样式。

    KmlDocument::placemark_count

    fn KmlDocument::placemark_count(self : KmlDocument) -> Int

    Placemark 数量。

    KmlDocument::style_count

    fn KmlDocument::style_count(self : KmlDocument) -> Int

    样式数量。

    KmlLineString

    pub(all) struct KmlLineString {
    points : Array[KmlPoint]
    }

    一条折线:有序的点列。

    KmlLineString::point_count

    fn KmlLineString::point_count(self : KmlLineString) -> Int

    折线的顶点数。

    KmlPoint

    pub(all) struct KmlPoint {
    lon : Double
    lat : Double
    alt : Double?
    }

    一个 WGS-84 坐标点。alt 缺省表示 KML 未给出高度。

    KmlPolygon

    pub(all) struct KmlPolygon {
    outer : LinearRing
    inner : Array[LinearRing]
    }

    一个多边形:外环 + 零或多个内环(洞)。

    KmlPolygon::inner_count

    fn KmlPolygon::inner_count(self : KmlPolygon) -> Int

    多边形的内环数。

    KmlStyle

    pub(all) struct KmlStyle {
    id : String
    line_color : String?
    line_width : Double?
    fill_color : String?
    }

    一个样式定义:线条颜色与宽度、填充颜色。

    LinearRing

    pub(all) struct LinearRing {
    points : Array[KmlPoint]
    }

    一个闭合环;KML 要求首尾点相同。

    LinearRing::point_count

    fn LinearRing::point_count(self : LinearRing) -> Int

    环的顶点数。

    Placemark

    pub(all) struct Placemark {
    name : String
    description : String
    geometry : Geometry?
    style_url : String
    extended_data : Array[KmlData]
    }

    一个 Placemark。

    Placemark::data_count

    fn Placemark::data_count(self : Placemark) -> Int

    Placemark 的扩展数据条目数。

    Placemark::find_data

    fn Placemark::find_data(self : Placemark, name : String) -> String?

    按名字找扩展数据值。

    Placemark::has_geometry

    fn Placemark::has_geometry(self : Placemark) -> Bool

    是否有几何。

    Placemark::has_line_string

    fn Placemark::has_line_string(self : Placemark) -> Bool

    是否有折线几何。

    Placemark::has_multi_geometry

    fn Placemark::has_multi_geometry(self : Placemark) -> Bool

    是否为多重几何。

    Placemark::has_point

    fn Placemark::has_point(self : Placemark) -> Bool

    是否有点几何。

    XmlAttr

    pub(all) struct XmlAttr {
    name : String
    value : String
    }

    一个 XML 属性。

    XmlElement

    pub(all) struct XmlElement {
    name : String
    attrs : Array[XmlAttr]
    children : Array[XmlNode]
    }

    一个 XML 元素。

    XmlElement::attr

    fn XmlElement::attr(self : XmlElement, name : String) -> String?

    读取元素上第一个同名属性,没有则返回 None。

    XmlElement::child

    fn XmlElement::child(self : XmlElement, name : String) -> XmlElement?

    子元素中第一个同名的元素。

    XmlElement::text

    fn XmlElement::text(self : XmlElement) -> String

    直接文本子节点拼接后的内容(不含子元素内部的文本)。

    XmlNode

    pub(all) enum XmlNode {
    Element(XmlElement)
    Text(String)
    }

    XML 节点:元素或文本。

    ZipEntry

    pub(all) struct ZipEntry {
    name : String
    data : Bytes
    }

    一个 ZIP 条目(名字、内容与 CRC)。

    kmz_pack

    fn kmz_pack(doc : KmlDocument) -> Bytes

    把 KML 文档打包成 KMZ(含 doc.kml)。

    kmz_parse

    fn kmz_parse(data : Bytes) -> KmlDocument raise KmlError

    从 KMZ 字节解出 KML 文档。

    parse

    fn parse(text : String) -> KmlDocument raise KmlError

    解析 KML 文本。

    parse_xml

    fn parse_xml(input : String) -> XmlElement raise KmlError

    解析一个 XML 文档,返回根元素。

    serialize

    fn serialize(doc : KmlDocument) -> String

    把 KML 文档序列化成文本。

    to_geojson

    fn to_geojson(doc : KmlDocument) -> String

    把 KML 文档导出为 GeoJSON FeatureCollection。

    to_gpx

    fn to_gpx(doc : KmlDocument) -> String

    把 KML 文档导出为 GPX 1.1。

    zip_find

    fn zip_find(data : Bytes, name : String) -> Bytes? raise KmlError

    从 ZIP 里找第一个指定名字的条目内容。

    zip_pack

    fn zip_pack(entries : Array[ZipEntry]) -> Bytes

    打包若干条目成 ZIP 字节流。