问题
I'm trying to parse a Kml file in Java. Cause I need to take the coordinates of a Placemark, to generate a poligon in java, and use it.
But my problem , is that i'm using JAK this library to parse it, and i'm not able to extract the information that i want.(I read the "help" in the official page, but I didn't found any help abut my problem)
I'm trying to do something like that:
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();
But in this point I don't know how to extract the coordinates.
The file I'm trying to parse is this one: la basa
回答1:
Following the javadocs (unofficial) you need to check - using instanceof
- each Feature
whether is is a Placemark
, if yes cast to it and get the Geometry
which itself needs to be checked whether it is a Polygon
, if yes then cast to it. After that the path to the coordinates is the following (just as it come in the kml-file):
getOuterBoundaryIs > getlinearRing > getCoordinates
Here is how it looks like in code:
@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("");
}
}
回答2:
Came across this post, so here is part of the code of function I have been using in my app to extract Place mark name & coordinates from a 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>"));
}
}
}
回答3:
Thanks @A4L This is really an update and a more groovier way of doing the same So changed for Groovy and also attempts more types than the example given as well digs deep within a document layer:
/**
* 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
}
来源:https://stackoverflow.com/questions/15636303/extract-coordinates-from-kml-file-in-java