flex 中GML转换

package org.openscales.core.format
{
 import flash.utils.getQualifiedClassName;
 import flash.xml.XMLNode;
 import org.openscales.core.Util;
 import org.openscales.core.feature.Feature;
 import org.openscales.core.geometry.Collection;
 import org.openscales.core.geometry.LineString;
 import org.openscales.core.geometry.LinearRing;
 import org.openscales.core.geometry.MultiLineString;
 import org.openscales.core.geometry.MultiPoint;
 import org.openscales.core.geometry.MultiPolygon;
 import org.openscales.core.geometry.Point;
 import org.openscales.core.geometry.Polygon;
 import org.openscales.proj4as.Proj4as;
 import org.openscales.proj4as.ProjPoint;
 import org.openscales.proj4as.ProjProjection;
 import org.openscales.core.feature.Feature;
 import org.openscales.core.feature.PointFeature;
 import org.openscales.core.feature.MultiPointFeature;
 import org.openscales.core.feature.LineStringFeature;
 import org.openscales.core.feature.MultiLineStringFeature;
 import org.openscales.core.feature.PolygonFeature;
 import org.openscales.core.feature.MultiPolygonFeature;
 import org.openscales.core.Trace;
 /**
  * Read/Write GML. Supports the GML simple features profile.
  */
 public class GMLFormat extends Format
 {
  protected var _featureNS:String = "http://openscales.org/OpenScales";
  protected var _featureName:String = "featureMember";
  protected var _featurePrefix:String = "OpenScales"; 
  protected var _layerName:String = "features";
  protected var _geometryName:String = "geometry";
  protected var _collectionName:String = "FeatureCollection";
  protected var _gmlns:String = "http://www.opengis.net/gml";
  protected var _gmlprefix:String = "gml";
  protected var _wfsns:String = "http://www.opengis.net/wfs";
  protected var _wfsprefix:String = "wfs";
  private var _extractAttributes:Boolean = true;
  private var _dim:Number;
  /**
   * GMLFormat constructor
   *
   * @param extractAttributes
   *
   */
  public function GMLFormat(extractAttributes:Boolean = true) {
   this.extractAttributes = extractAttributes;
  }
  /**
   * Read data
   *
   * @param data data to read/parse.
   *
   * @return features.
   */
  override public function read(data:Object):Object {
   var dataXML:XML = null;
   if (typeof data == "string") { 
    dataXML = new XML(data);
   } else {
    dataXML = XML(data);
   }
   var featureNodes:XMLList = dataXML..*::featureMember;
   if (featureNodes.length() == 0) { return []; }
   var dim:int;
   var coordNodes:XMLList = featureNodes[0].*::posList;
   if (coordNodes.length() == 0) {
    coordNodes = featureNodes[0].*::pos;
   }
   if (coordNodes.length() > 0) {
    dim = coordNodes[0].@*::srsDimension;
   }    
   this.dim = (dim == 3) ? 3 : 2;
   var features:Array = [];
   for (var i:int = 0; i < featureNodes.length(); i++) {
    var feature:Feature = this.parseFeature(featureNodes[i]);
    if (feature) {
     features.push(feature);
    }
   }
   return features;
  }
  /**
   *    It creates the geometries that are then attached to the returned
   *    feature, and calls parseAttributes() to get attribute data out.
   * 
   *    Important note: All geom node names 'the_geom.*::' have been removed 
   *    until a config is implemented to be able to parse the geom nodes in a
   *    generic way. See Issue 185 for more info.
   *
   * @param node A XML feature node.
   *
   * @return A vetor of feature
   */
  public function parseFeature(xmlNode:XML):Feature {
   var geom:Collection = null;
   var p:Array = new Array();
   var feature:Feature = null;
   if (xmlNode..*::MultiPolygon.length() > 0) {
    var multipolygon:XML = xmlNode..*::MultiPolygon[0];
    geom = new MultiPolygon();
    var polygons:XMLList = multipolygon..*::Polygon;
    for (var i:int = 0; i < polygons.length(); i++) {
     var polygon:Polygon = this.parsePolygonNode(polygons[i]);
     geom.addComponent(polygon);
    }
   } else if (xmlNode..*::MultiLineString.length() > 0) {
    var multilinestring:XML = xmlNode..*::MultiLineString[0];
    geom = new MultiLineString();
    var lineStrings:XMLList = multilinestring..*::LineString;
    for (i = 0; i < lineStrings.length(); i++) {
     p = this.parseCoords(lineStrings[i]);
     if(p){
      var lineString:LineString = new LineString(p);
      geom.addComponent(lineString);
     }
    }
   } else if (xmlNode..*::MultiPoint.length() > 0) {
    var multiPoint:XML = xmlNode..*::MultiPoint[0];
    geom = new MultiPoint();
    var points:XMLList = multiPoint..*::Point;
    for (i = 0; i < points.length(); i++) {
     p = this.parseCoords(points[i]);
     geom.addComponents(p[0]);
    }
   } else if (xmlNode..*::Polygon.length() > 0) {
    var polygon2:XML = xmlNode..*::Polygon[0];
    geom = this.parsePolygonNode(polygon2);
   } else if (xmlNode..*::LineString.length() > 0) {
    var lineString2:XML = xmlNode..*::LineString[0];
    p = this.parseCoords(lineString2);
    if (p) {
     geom = new LineString(p);
    }
   } else if (xmlNode..*::Point.length() > 0) {
    var point:XML = xmlNode..*::Point[0];
    geom = new MultiPoint();
    p = this.parseCoords(point);
    if (p) {
     geom.addComponent(p[0]);
    }
   }
   if (geom) {
    // Test more specific geom before because for is operator, a lineString is a multipoint for example (inheritance) 
    if (geom is MultiPolygon) {
     feature = new MultiPolygonFeature(geom as MultiPolygon);
    } else if (geom is Polygon) {
     feature = new PolygonFeature(geom as Polygon);
    } else if (geom is MultiLineString) {
     feature = new MultiLineStringFeature(geom as MultiLineString);
    } else if (geom is LineString) {
     feature = new LineStringFeature(geom as LineString);
    } else if (geom is MultiPoint) {
     feature = new MultiPointFeature(geom as MultiPoint);
    } else if (geom is Point) {
     feature = new PointFeature(geom as Point);
    } else {
     Trace.warning("GMLFormat.parseFeature: unrecognized geometry);"); 
     return null; 
    }
    feature.name = xmlNode..@fid;
    if (this.extractAttributes) {
     feature.attributes = this.parseAttributes(xmlNode);
    }    
    return feature;
   } else {
    return null;
   }
  }
  /**
   * Parse attributes
   *
   * @param node A XML feature node.
   *
   * @return An attributes object.
   */
  public function parseAttributes(xmlNode:XML):Object {
   var nodes:XMLList = xmlNode.children();
   var attributes:Object = {};
   for(var i:int = 0; i < nodes.length(); i++) {
    var name:String = nodes[i].localName();
    var value:Object = nodes[i].valueOf();
    if(name == null){
     continue;    
    }
    // Check for a leaf node
    if((nodes[i].children().length() == 1)
     && !(nodes[i].children().children()[0] is XML)) {
     attributes[name] = value.children()[0].toXMLString();
    }
    Util.extend(attributes, this.parseAttributes(nodes[i]));
   }   
   return attributes;
  }
  /**
   * Given a GML node representing a polygon geometry
   *
   * @param node
   *
   * @return A polygon geometry.
   */
  public function parsePolygonNode(polygonNode:Object):Polygon {
   var linearRings:XMLList = polygonNode..*::LinearRing;
   // Optimize by specifying the array size
   var rings:Array = new Array(linearRings.length());
   for (var i:int = 0; i < linearRings.length(); i++) {
    rings[i] = new LinearRing(this.parseCoords(linearRings[i]));
   }
   return new Polygon(rings);
  }
  /**
   * Return an array of coords
   */ 
  public function parseCoords(xmlNode:XML):Array {
   var x:Number, y:Number, left:Number, bottom:Number, right:Number, top:Number;
   var points:Array = new Array();
   if (xmlNode) {
    var coordNodes:XMLList = xmlNode.*::posList;
    if (coordNodes.length() == 0) { 
     coordNodes = xmlNode.*::pos;
    }    
    if (coordNodes.length() == 0) {
     coordNodes = xmlNode.*::coordinates;
    }    
    var coordString:String = coordNodes[0].text();
    var nums:Array = (coordString) ? coordString.split(/[, /n/t]+/) : [];
    while (nums[0] == "") 
     nums.shift();
    while (nums[nums.length-1] == "") 
     nums.pop();
    for(var i:int = 0; i < nums.length; i = i + this.dim) {
     x = Number(nums[i]);
     y = Number(nums[i+1]);
     var p:Point = new Point(x, y);
     if (this._internalProj != null, this._externalProj != null)
      p.transform(this.externalProj, this.internalProj);
     points.push(p);
    }
    return points
   }
   return points;
  }
  /**
   * Generate a GML document object given a list of features.
   *
   * @param features List of features to serialize into an object.
   *
   * @return An object representing the GML document.
   */
  override public function write(features:Object):Object {
   var featureCollection:XML = new XML("<" + this._wfsprefix + ":" + this._collectionName + " xmlns:" + this._wfsprefix + "=/"" + this._wfsns + "/"></" + this._wfsprefix + ":" + this._collectionName + ">");
   for (var i:int=0; i < features.length; i++) {
    featureCollection.appendChild(this.createFeatureXML(features[i]));
   }
   return featureCollection;
  }
  /**
   * Accept a Vector feature, and build a GML node for it.
   *
   * @param feature The feature to be built as GML.
   *
   * @return A node reprensting the feature in GML.
   */
  public function createFeatureXML(feature:Feature):XML {
   var geometryNode:XML = this.buildGeometryNode(feature.geometry);
   var geomContainer:XML = new XML("<" + this._gmlprefix + ":" + this._geometryName + " xmlns:" + this._gmlprefix + "=/"" + this._gmlns + "/"></" + this._gmlprefix + ":" + this._geometryName + ">");
   geomContainer.appendChild(geometryNode);
   var featureNode:XML = new XML("<" + this._gmlprefix + ":" + this._featureName + " xmlns:" + this._gmlprefix + "=/"" + this._gmlns + "/"></" + this._gmlprefix + ":" + this._featureName + ">");
   var featureContainer:XML = new XML("<OpenScales:" + this._featureName + " xmlns:" + this._featurePrefix + "=/"" + this._featureNS + "/"></" + this._featurePrefix + ":" + this._layerName + ">");
   featureContainer.appendChild(geomContainer);
   for(var attr:String in feature.attributes) {
    var attrText:XMLNode = new XMLNode(2, feature.attributes[attr]); 
    var nodename:String = attr;
    if (attr.search(":") != -1) {
     nodename = attr.split(":")[1];
    }    
    var attrContainer:XML = new XML("<" + this._featurePrefix + ":" + nodename + " xmlns:" + this._featurePrefix + "=/"" + this._featureNS + "/"></" + this._featurePrefix + ":" + nodename + ">");
    attrContainer.appendChild(attrText);
    featureContainer.appendChild(attrContainer);
   }    
   featureNode.appendChild(featureContainer);
   return featureNode;
  }
  /**
   * create a GML Object
   *
   * @param geometry
   *
   * @return an XML
   */
  public function buildGeometryNode(geometry:Object):XML {
   var gml:XML;
   if (getQualifiedClassName(geometry) == "org.openscales.core.geometry::MultiPolygon"
    || getQualifiedClassName(geometry) == "org.openscales.core.geometry::Polygon") {
    gml = new XML("<" + this._gmlprefix + ":MultiPolygon xmlns:" + this._gmlprefix + "=/"" + this._gmlns + "/"></" + this._gmlprefix + ":MultiPolygon>");
    var polygonMember:XML = new XML("<" + this._gmlprefix + ":polygonMember xmlns:" + this._gmlprefix + "=/"" + this._gmlns + "/"></" + this._gmlprefix + ":polygonMember>");
    var polygon:XML = new XML("<" + this._gmlprefix + ":Polygon xmlns:" + this._gmlprefix + "=/"" + this._gmlns + "/"></" + this._gmlprefix + ":Polygon>");
    var outerRing:XML = new XML("<" + this._gmlprefix + ":outerBoundaryIs xmlns:" + this._gmlprefix + "=/"" + this._gmlns + "/"></" + this._gmlprefix + ":outerBoundaryIs>");
    var linearRing:XML = new XML("<" + this._gmlprefix + ":LinearRing xmlns:" + this._gmlprefix + "=/"" + this._gmlns + "/"></" + this._gmlprefix + ":LinearRing>");
    linearRing.appendChild(this.buildCoordinatesNode(geometry.components[0]));
    outerRing.appendChild(linearRing);
    polygon.appendChild(outerRing);
    polygonMember.appendChild(polygon);
    gml.appendChild(polygonMember);
   }
   else if (getQualifiedClassName(geometry) == "org.openscales.core.geometry::MultiLineString"
    || getQualifiedClassName(geometry) == "org.openscales.core.geometry::LineString") {
    gml = new XML("<" + this._gmlprefix + ":MultiLineString xmlns:" + this._gmlprefix + "=/"" + this._gmlns + "/"></" + this._gmlprefix + ":MultiLineString>");
    var lineStringMember:XML = new XML("<" + this._gmlprefix + ":lineStringMember xmlns:" + this._gmlprefix + "=/"" + this._gmlns + "/"></" + this._gmlprefix + ":lineStringMember>");
    var lineString:XML = new XML("<" + this._gmlprefix + ":LineString xmlns:" + this._gmlprefix + "=/"" + this._gmlns + "/"></" + this._gmlprefix + ":LineString>");
    lineString.appendChild(this.buildCoordinatesNode(geometry));
    lineStringMember.appendChild(lineString);
    gml.appendChild(lineStringMember);
   }
   else if (getQualifiedClassName(geometry) == "org.openscales.core.geometry::MultiPoint") {
    gml = new XML("<" + this._gmlprefix + ":MultiPoint xmlns:" + this._gmlprefix + "=/"" + this._gmlns + "/"></" + this._gmlprefix + ":MultiPoint>");
    var parts:Object = "";
    parts = geometry.components;   
    for (var i:int = 0; i < parts.length; i++) { 
     var pointMember:XML = new XML("<" + this._gmlprefix + ":pointMember xmlns:" + this._gmlprefix + "=/"" + this._gmlns + "/"></" + this._gmlprefix + ":pointMember>");
     var point:XML = new XML("<" + this._gmlprefix + ":Point xmlns:" + this._gmlprefix + "=/"" + this._gmlns + "/"></" + this._gmlprefix + ":Point>");
     point.appendChild(this.buildCoordinatesNode(parts[i]));
     pointMember.appendChild(point);
     gml.appendChild(pointMember);
    }     
   } else if (getQualifiedClassName(geometry) == "org.openscales.core.geometry::Point") {
    parts = geometry;
    gml = new XML("<" + this._gmlprefix + ":Point xmlns:" + this._gmlprefix + "=/"" + this._gmlns + "/"></" + this._gmlprefix + ":Point>");
    gml.appendChild(this.buildCoordinatesNode(parts));
   }
   return gml; 
  }
  /**
   * Builds the coordinates XmlNode
   *
   * @param geometry
   *
   * @return created xmlNode
   */
  public function buildCoordinatesNode(geometry:Object):XML {
   var coordinatesNode:XML = new XML("<" + this._gmlprefix + ":coordinates xmlns:" + this._gmlprefix + "=/"" + this._gmlns + "/"></" + this._gmlprefix + ":coordinates>");
   coordinatesNode.@decimal = ".";
   coordinatesNode.@cs = ",";
   coordinatesNode.@ts = " ";
   var points:Array = null;
   if (geometry.components) {
    if (geometry.components.length > 0) {
     points = geometry.components;
    }
   }
   var path:String = "";
   if (points) {
    for (var i:int = 0; i < points.length; i++) {
     if (this.internalProj != null && this.externalProj != null)
      (points[i] as Point).transform(this.internalProj, this.externalProj);
     path += points[i].x + "," + points[i].y + " ";
    }
   } else {
    if (this.internalProj != null && this.externalProj != null) {
     var p:ProjPoint = new ProjPoint(geometry.x, geometry.y);
     Proj4as.transform(internalProj, externalProj, p);
     geometry.x = p.x;
     geometry.y = p.y;
    }
    path += geometry.x + "," + geometry.y + " ";
   }    
   coordinatesNode.appendChild(path);
   return coordinatesNode;
  }
  //Getters and Setters
  public function get extractAttributes():Boolean {
   return this._extractAttributes;
  }
  public function set extractAttributes(value:Boolean):void {
   this._extractAttributes = value;
  }
  public function get dim():Number {
   return this._dim;
  }
  public function set dim(value:Number):void {
   this._dim = value;
  }
  public function get internalProj():ProjProjection {
   return this._internalProj;
  }
  public function set internalProj(value:ProjProjection):void {
   this._internalProj = value;
  }
  public function get externalProj():ProjProjection {
   return this._externalProj;
  }
  public function set externalProj(value:ProjProjection):void {
   this._externalProj = value;
  }
 }
}

你可能感兴趣的:(flex 中GML转换)