我正在尝试用Java解析Kml文件。因为我需要获取地标的坐标,在java中生成一个poligon,然后使用它。
但是我的问题是,我正在使用JAK这个库来解析它,而我无法提取我想要的信息。(我在官方页面中阅读了“帮助”,但是我没有找到任何帮助来解决我的问题)
我正在尝试做类似的事情:
final Kml kml = Kml.unmarshal(new File("C:/Users/A556520/Documents/Proyectos/GeoFencing/res/labasa.kml"));
final Document document = (Document)kml.getFeature();
List<Feature> listafeatures = document.getFeature();
但是在这一点上我不知道如何提取坐标。
我正在尝试解析的文件是:la basa
答案 0 :(得分:10)
关注javadocs(unofficial),您需要检查 - 使用instanceof
- 每个Feature
是否为Placemark
,如果是,则为{}并获取Geometry
本身需要检查它是否是Polygon
,如果是,则转换为它。之后,坐标的路径如下(就像它在kml文件中一样):
getOuterBoundaryIs > getlinearRing > getCoordinates
以下是代码中的样子:
@Test
public void parseKml() {
String src = "misctests/stackoverflow/kml/labasa.kml";
try(InputStream is = getClass().getClassLoader().getResourceAsStream(src)) {
Assert.assertNotNull(is);
Kml kml = Kml.unmarshal(is);
Feature feature = kml.getFeature();
parseFeature(feature);
}
}
private void parseFeature(Feature feature) {
if(feature != null) {
if(feature instanceof Document) {
Document document = (Document) feature;
List<Feature> featureList = document.getFeature();
for(Feature documentFeature : featureList) {
if(documentFeature instanceof Placemark) {
Placemark placemark = (Placemark) documentFeature;
Geometry geometry = placemark.getGeometry();
parseGeometry(geometry);
}
}
}
}
}
private void parseGeometry(Geometry geometry) {
if(geometry != null) {
if(geometry instanceof Polygon) {
Polygon polygon = (Polygon) geometry;
Boundary outerBoundaryIs = polygon.getOuterBoundaryIs();
if(outerBoundaryIs != null) {
LinearRing linearRing = outerBoundaryIs.getLinearRing();
if(linearRing != null) {
List<Coordinate> coordinates = linearRing.getCoordinates();
if(coordinates != null) {
for(Coordinate coordinate : coordinates) {
parseCoordinate(coordinate);
}
}
}
}
}
}
}
private void parseCoordinate(Coordinate coordinate) {
if(coordinate != null) {
System.out.println("Longitude: " + coordinate.getLongitude());
System.out.println("Latitude : " + coordinate.getLatitude());
System.out.println("Altitude : " + coordinate.getAltitude());
System.out.println("");
}
}
答案 1 :(得分:1)
遇到过这篇文章,所以这里是我在我的应用程序中用来提取Place标记名称和功能的函数代码的一部分。来自String kmlText的坐标。
if (kmlText != null & kmlText.length() > 0) {
// Change case of relevant tags to match our search string case
kmlText = kmlText.replaceAll("(?i)<Placemark>", "<Placemark>")
.replaceAll("(?i)</Placemark>", "</Placemark>")
.replaceAll("(?i)<name>", "<name>")
.replaceAll("(?i)</name>", "</name>")
.replaceAll("(?i)<coordinates>", "<coordinates>")
.replaceAll("(?i)</coordinates>", "</coordinates>");
// Get <Placemark> tag
String[] kmlPlacemarks = kmlText.split("</Placemark>");
if (kmlPlacemarks.length > 0) {
for (Integer i = 0; i < kmlPlacemarks.length; i++) {
// Add '</Placemark>' to the end - actually not necessary
kmlPlacemarks[i] += "</Placemark>";
if (kmlPlacemarks[i].indexOf("<Placemark>") > -1)
/* Trim front to start from '<Placemark>'
Otherwise additional tags may be in between leading
to parsing of incorrect values especially Name */
kmlPlacemarks[i] = kmlPlacemarks[i].substring(kmlPlacemarks[i].indexOf("<Placemark>"));
}
String tmpPlacemarkName;
String tmpPlacemarkCoordinates;
for (String kmlPlacemark: kmlPlacemarks)
if ((kmlPlacemark.indexOf("<name>") > -1 && kmlPlacemark.indexOf("</name>") > -1) &&
(kmlPlacemark.indexOf("<coordinates>") > -1 && kmlPlacemark.indexOf("</coordinates>") > -1)) {
tmpPlacemarkCoordinates = kmlPlacemark.substring(kmlPlacemark.indexOf("<coordinates>") + 13, kmlPlacemark.indexOf("</coordinates>"));
tmpPlacemarkName = kmlPlacemark.substring(kmlPlacemark.indexOf("<name>") + 6, kmlPlacemark.indexOf("</name>"));
}
}
}
答案 2 :(得分:0)
谢谢@ A4L这真的是一个更新和更加更加时髦的方式做同样的事情因此改变了Groovy并尝试了更多的类型而不是给出的示例以及深入挖掘文档层:
/**
* This starts the process and reads in the uk file
*/
public static void parseKml() {
def src = ServletContextHolder.servletContext.getRealPath("/KML/doc.kml")
InputStream is = new FileInputStream(src);
Kml kml = Kml.unmarshal(is);
Feature feature = kml.getFeature();
parseFeature(feature);
}
/**
* This is step 2 of the process it figures out if it has a direct placemark mapping on kml
* or if this is part of some big folder structure
* @param feature
*/
public static void parseFeature(Feature feature) {
if(feature) {
if(feature instanceof Document) {
feature?.feature?.each { documentFeature->
if(documentFeature instanceof Placemark) {
getPlacemark((Placemark) documentFeature)
} else if (documentFeature instanceof Folder) {
getFeatureList(documentFeature.feature)
}
}
}
}
}
/**
* This iterates over itself over and over again to gain access to placemarks within folders
* The uk map boundary was nested folders within folders
* @param features
* @return
*/
public static List<Feature> getFeatureList(List<Feature> features) {
features?.each { Feature f ->
if (f instanceof Folder) {
getFeatureList(f.getFeature())
} else if (f instanceof Placemark) {
getPlacemark((Placemark) f)
}
}
}
/**
* This in short kicks off looking at a placemark it's name then parsing through each of its geometry points
* This controls the listener content or should I say builds it up from within this helper
* @param placemark
*/
public static void getPlacemark(Placemark placemark) {
Geometry geometry = placemark.getGeometry()
List results = parseGeometry(geometry)
GeoMapListener.update(placemark.name, results)
}
private static List parseGeometry(Geometry geometry) {
List results=[]
if(geometry != null) {
if(geometry instanceof Polygon) {
Polygon polygon = (Polygon) geometry;
Boundary outerBoundaryIs = polygon.getOuterBoundaryIs();
if(outerBoundaryIs != null) {
LinearRing linearRing = outerBoundaryIs.getLinearRing();
if(linearRing != null) {
List<Coordinate> coordinates = linearRing.getCoordinates();
if(coordinates != null) {
for(Coordinate coordinate : coordinates) {
results << parseCoordinate(coordinate);
}
}
}
}
} else if (geometry instanceof LineString) {
LineString lineString = (LineString) geometry;
List<Coordinate> coordinates = lineString.getCoordinates();
if (coordinates != null) {
for (Coordinate coordinate : coordinates) {
results << parseCoordinate(coordinate);
}
}
}
}
return results
}
private static Map parseCoordinate(Coordinate coordinate) {
Map results=[:]
if(coordinate) {
results.longitude= coordinate.longitude
results.latitude= coordinate.latitude
results.altitude= coordinate.altitude
}
return results
}
答案 3 :(得分:0)
关于A4L答案,非常感谢,我添加了更多的提取方法,这些方法将使用javaapi4kml使用包使用spring MVC从文件夹和文档中通过点线和多边形提取来获取数据
<dependency>
<groupId>de.micromata.jak</groupId>
<artifactId>JavaAPIforKml</artifactId>
<version>2.2.0</version>
</dependency>
@RequestMapping(value = "/testKml", method = RequestMethod.POST)
public Map<String, Object> parseKml(@RequestBody Map<String, Object> data){
Map<String, Object> response = new HashMap<String, Object>();
List<Map<String, Object>> wktObjrow = new ArrayList<Map<String, Object>>();
String src = data.get("kmlfile").toString();
try {
URL url;
url = new URL(src);
URLConnection conn = url.openConnection();
InputStream is = url.openStream();
Assert.notNull(is);
Kml kml = Kml.unmarshal(is);
Feature feature = kml.getFeature();
Map<String, Object> geodata = new HashMap<String, Object>();
if(feature != null) {
if(feature instanceof Document) {
Document document = (Document) feature;
List<Feature> featureList = document.getFeature();
for(Feature documentFeature : featureList) {
if(documentFeature instanceof Placemark) {
geodata = new HashMap<String, Object>();
Placemark placemark = (Placemark) documentFeature;
Geometry geometry = placemark.getGeometry();
geodata = parseGeometry(geometry, documentFeature.getName().toString());
if(!geodata.isEmpty())
{
wktObjrow.add(geodata);
}
}
else if(documentFeature instanceof Folder)
{
Folder folder = (Folder) documentFeature;
List<Feature> folderfeaturList = folder.getFeature();
for(Feature folderfeature : folderfeaturList)
{
geodata = new HashMap<String, Object>();
if(folderfeature instanceof Placemark) {
Placemark placemark = (Placemark) folderfeature;
Geometry geometry = placemark.getGeometry();
//push each of return store in list
geodata = parseGeometry(geometry, placemark.getName().toString());
if(!geodata.isEmpty())
{
wktObjrow.add(geodata);
}
}
else
{
System.err.println("folderfeatures was not of type Placemark");
}
}
}
else
{
System.err.println("Was not instance of Placemark or Folder");
}
}
System.out.println("wktObjrow : "+wktObjrow);
}
else
{
System.err.println("instance of feature was Not Document");
if(feature instanceof Folder) {
Folder folder = (Folder) feature;
List<Feature> featureList = folder.getFeature();
geodata = new HashMap<String, Object>();
for(Feature documentFeature : featureList) {
if(documentFeature instanceof Placemark) {
Placemark placemark = (Placemark) documentFeature;
Geometry geometry = placemark.getGeometry();
if(documentFeature.getName().toString().length() > 0)
{
geodata = parseGeometry(geometry, documentFeature.getName().toString());
if(!geodata.isEmpty())
{
wktObjrow.add(geodata);
}
}
else
{
geodata = parseGeometry(geometry, placemark.getName().toString());
if(!geodata.isEmpty())
{
wktObjrow.add(geodata);
}
}
}else
{
System.err.println("Was not instance of Placemark");
}
}
System.out.println("wktObjrow : "+wktObjrow);
}
}
}
else
{
System.err.println("Feature was null");
response.put("Null", "Feature was null");
}
}
catch (Exception e) {
// TODO: handle exception
System.err.println("Exception @ : "+ e);
}
if(!wktObjrow.isEmpty() && wktObjrow != null)
{
response.put("data", wktObjrow);
}
return response;
}
public Map<String, Object> parseGeometry(Geometry geometry,String name) {
// <Point> <LinearRing> <Geometry> <Model> <LineString> <Polygon> <MultiGeometry>
Map<String, Object> response = new HashMap<String, Object>();
List<Map<String, Object>> wktObjrow = new ArrayList<Map<String, Object>>();
if(geometry != null) {
if(geometry instanceof Polygon) {
Polygon polygon = (Polygon) geometry;
Boundary outerBoundaryIs = polygon.getOuterBoundaryIs();
if(outerBoundaryIs != null) {
LinearRing linearRing = outerBoundaryIs.getLinearRing();
if(linearRing != null) {
List<Coordinate> coordinates = linearRing.getCoordinates();
if(coordinates != null) {
Map<String, Object> map = new HashMap<String, Object>();
ArrayList<String> wkt_lonlat = new ArrayList<String>();
for(Coordinate coordinate : coordinates) {
wkt_lonlat.add(coordinate.getLongitude()+" "+coordinate.getLatitude());
}
response.put("name",name);
response.put("category","POLYGON");
response.put("row","POLYGON(("+String.join(",", wkt_lonlat)+"))");
}
else
{
System.err.println("coordinate was null");
}
}
}
}
else if(geometry instanceof Point)
{
Point point = (Point) geometry;
List<Coordinate> coordinates = point.getCoordinates();
if(coordinates != null && !coordinates.isEmpty())
{
if(coordinates != null) {
for(Coordinate coordinate : coordinates) {
Map<String, Object> map = new HashMap<String, Object>();
response.put("lon",coordinate.getLongitude());
response.put("lat",coordinate.getLatitude());
response.put("name",name);
response.put("category","POINT");
}
}
}
}
else if(geometry instanceof LineString)
{
LineString line = (LineString) geometry;
List<Coordinate> coordinates = line.getCoordinates();
if(coordinates != null && !coordinates.isEmpty())
{
if(coordinates != null) {
Map<String, Object> map = new HashMap<String, Object>();
ArrayList<String> wkt_lonlat = new ArrayList<String>();
for(Coordinate coordinate : coordinates) {
wkt_lonlat.add(coordinate.getLongitude()+" "+coordinate.getLatitude());
}
response.put("name",name);
response.put("category","LINESTRING");
response.put("row","LINESTRING("+String.join(",", wkt_lonlat)+")");
}
}
}
else if(geometry instanceof MultiGeometry)
{
MultiGeometry multigeometry = (MultiGeometry) geometry;
for (int j = 0; j < multigeometry.getGeometry().size(); j++) {
if(multigeometry.getGeometry().get(j) instanceof LineString)
{
LineString line = (LineString) multigeometry.getGeometry().get(j);
List<Coordinate> coordinates = line.getCoordinates();
if(coordinates != null && !coordinates.isEmpty())
{
if(coordinates != null) {
Map<String, Object> map = new HashMap<String, Object>();
ArrayList<String> wkt_lonlat = new ArrayList<String>();
for(Coordinate coordinate : coordinates) {
wkt_lonlat.add(coordinate.getLongitude()+" "+coordinate.getLatitude());
}
response.put("name",name);
response.put("category","LINESTRING");
response.put("row","LINESTRING("+String.join(",", wkt_lonlat)+")");
}
}
}
else if(multigeometry.getGeometry().get(j) instanceof Point)
{
Point point = (Point) multigeometry.getGeometry().get(j);
List<Coordinate> coordinates = point.getCoordinates();
if(coordinates != null && !coordinates.isEmpty())
{
if(coordinates != null) {
for(Coordinate coordinate : coordinates) {
Map<String, Object> map = new HashMap<String, Object>();
response.put("lon",coordinate.getLongitude());
response.put("lat",coordinate.getLatitude());
response.put("name",name);
response.put("category","POINT");
}
}
}
}
else if(multigeometry.getGeometry().get(j) instanceof Polygon)
{
Polygon polygon = (Polygon) multigeometry.getGeometry().get(j);
Boundary outerBoundaryIs = polygon.getOuterBoundaryIs();
if(outerBoundaryIs != null) {
LinearRing linearRing = outerBoundaryIs.getLinearRing();
if(linearRing != null) {
List<Coordinate> coordinates = linearRing.getCoordinates();
if(coordinates != null) {
Map<String, Object> map = new HashMap<String, Object>();
ArrayList<String> wkt_lonlat = new ArrayList<String>();
for(Coordinate coordinate : coordinates) {
wkt_lonlat.add(coordinate.getLongitude()+" "+coordinate.getLatitude());
}
response.put("name",name);
response.put("category","POLYGON");
response.put("row","POLYGON(("+String.join(",", wkt_lonlat)+"))");
}
else
{
System.err.println("coordinate was null");
}
}
}
}
}
}
}
else
{
System.err.println("geometry was null");
response.put("Null", "geometry was null");
}
return response;
}
答案 4 :(得分:0)
上述答案使用了现在似乎不受支持的库 de.micromata.opengis.kml。 有一个更新的库,OSM Bonus Pack,它有一个很好的 KmlDocument 类。我用它来提取坐标如下。它只提取线(道路),不提取多边形,但它应该是可修改的。
List<List<GeoPoint>> roads = new ArrayList<List<GeoPoint>>();
public void parseKmlDocument(KmlDocument doc) {
int index = 0;
for (KmlFeature kmlf: doc.mKmlRoot.mItems) {
if ((kmlf instanceof KmlPlacemark))
{
KmlPlacemark placemark = (KmlPlacemark)kmlf;
KmlGeometry kmlg = placemark.mGeometry;
if (kmlg instanceof KmlMultiGeometry)
{
KmlMultiGeometry kmlmg = (KmlMultiGeometry)kmlg;
for (KmlGeometry thisKmlg: kmlmg.mItems)
{
ArrayList<GeoPoint> mCoordinates = thisKmlg.mCoordinates;
roads.add(index++, mCoordinates);
}
}
}
else {
// kmlg is a LineString
ArrayList<GeoPoint> mCoordinates = kmlg.mCoordinates;
Road road = new Road(mCoordinates);
roads.add(road);
++rIndex;
}
}
// checking the result
int road = 0 ;
int gpoint = 0;
for (List<GeoPoint> listGp: roads) {
Log.d("road ", String.valueOf(road++));
for (GeoPoint gp: listGp) {
gpoint++;
Log.d(" coords ",gp.getLatitude() + " " + gp.getLongitude());
}
}
Log.d("Summary ",road + " roads containing " + gpoint + " geopoints");
}