Merge pull request #6196 from raiyni/ExtendedData
KML ExtendedData Export
This commit is contained in:
@@ -2278,6 +2278,54 @@ ol.format.KML.writeCoordinatesTextNode_ = function(node, coordinates, objectStac
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Node} node Node.
|
||||||
|
* @param {{name: *, value: *}} pair Name value pair.
|
||||||
|
* @param {Array.<*>} objectStack Object stack.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
ol.format.KML.writeDataNode_ = function(node, pair, objectStack) {
|
||||||
|
node.setAttribute('name', pair.name);
|
||||||
|
var /** @type {ol.XmlNodeStackItem} */ context = {node: node};
|
||||||
|
var value = pair.value;
|
||||||
|
|
||||||
|
if (typeof value == 'object') {
|
||||||
|
if (value !== null && value.displayName) {
|
||||||
|
ol.xml.pushSerializeAndPop(context, ol.format.KML.EXTENDEDDATA_NODE_SERIALIZERS_,
|
||||||
|
ol.xml.OBJECT_PROPERTY_NODE_FACTORY, [value.displayName], objectStack, ['displayName']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value !== null && value.value) {
|
||||||
|
ol.xml.pushSerializeAndPop(context, ol.format.KML.EXTENDEDDATA_NODE_SERIALIZERS_,
|
||||||
|
ol.xml.OBJECT_PROPERTY_NODE_FACTORY, [value.value], objectStack, ['value']);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ol.xml.pushSerializeAndPop(context, ol.format.KML.EXTENDEDDATA_NODE_SERIALIZERS_,
|
||||||
|
ol.xml.OBJECT_PROPERTY_NODE_FACTORY, [value], objectStack, ['value']);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Node} node Node to append a TextNode with the name to.
|
||||||
|
* @param {string} name DisplayName.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
ol.format.KML.writeDataNodeName_ = function(node, name) {
|
||||||
|
ol.format.XSD.writeCDATASection(node, name);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Node} node Node to append a CDATA Section with the value to.
|
||||||
|
* @param {string} value Value.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
ol.format.KML.writeDataNodeValue_ = function(node, value) {
|
||||||
|
ol.format.XSD.writeStringTextNode(node, value);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Node} node Node.
|
* @param {Node} node Node.
|
||||||
* @param {Array.<ol.Feature>} features Features.
|
* @param {Array.<ol.Feature>} features Features.
|
||||||
@@ -2293,6 +2341,24 @@ ol.format.KML.writeDocument_ = function(node, features, objectStack) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Node} node Node.
|
||||||
|
* @param {{names: Array<string>, values: (Array<*>)}} namesAndValues Names and values.
|
||||||
|
* @param {Array.<*>} objectStack Object stack.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
ol.format.KML.writeExtendedData_ = function(node, namesAndValues, objectStack) {
|
||||||
|
var /** @type {ol.XmlNodeStackItem} */ context = {node: node};
|
||||||
|
var names = namesAndValues.names, values = namesAndValues.values;
|
||||||
|
var length = names.length;
|
||||||
|
|
||||||
|
for (var i = 0; i < length; i++) {
|
||||||
|
ol.xml.pushSerializeAndPop(context, ol.format.KML.EXTENDEDDATA_NODE_SERIALIZERS_,
|
||||||
|
ol.format.KML.DATA_NODE_FACTORY_, [{name: names[i], value: values[i]}], objectStack);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Node} node Node.
|
* @param {Node} node Node.
|
||||||
* @param {Object} icon Icon object.
|
* @param {Object} icon Icon object.
|
||||||
@@ -2490,6 +2556,21 @@ ol.format.KML.writePlacemark_ = function(node, feature, objectStack) {
|
|||||||
// serialize properties (properties unknown to KML are not serialized)
|
// serialize properties (properties unknown to KML are not serialized)
|
||||||
var properties = feature.getProperties();
|
var properties = feature.getProperties();
|
||||||
|
|
||||||
|
// don't export these to ExtendedData
|
||||||
|
var filter = {'address': 1, 'description': 1, 'name': 1, 'open': 1,
|
||||||
|
'phoneNumber': 1, 'styleUrl': 1, 'visibility': 1};
|
||||||
|
filter[feature.getGeometryName()] = 1;
|
||||||
|
var keys = Object.keys(properties || {}).sort().filter(function(v) {
|
||||||
|
return !filter[v];
|
||||||
|
});
|
||||||
|
|
||||||
|
if (keys.length > 0) {
|
||||||
|
var sequence = ol.xml.makeSequence(properties, keys);
|
||||||
|
var namesAndValues = {names: keys, values: sequence};
|
||||||
|
ol.xml.pushSerializeAndPop(context, ol.format.KML.PLACEMARK_SERIALIZERS_,
|
||||||
|
ol.format.KML.EXTENDEDDATA_NODE_FACTORY_, [namesAndValues], objectStack);
|
||||||
|
}
|
||||||
|
|
||||||
var styleFunction = feature.getStyleFunction();
|
var styleFunction = feature.getStyleFunction();
|
||||||
if (styleFunction) {
|
if (styleFunction) {
|
||||||
// FIXME the styles returned by the style function are supposed to be
|
// FIXME the styles returned by the style function are supposed to be
|
||||||
@@ -2678,6 +2759,19 @@ ol.format.KML.DOCUMENT_SERIALIZERS_ = ol.xml.makeStructureNS(
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @const
|
||||||
|
* @type {Object.<string, Object.<string, ol.XmlSerializer>>}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
ol.format.KML.EXTENDEDDATA_NODE_SERIALIZERS_ = ol.xml.makeStructureNS(
|
||||||
|
ol.format.KML.NAMESPACE_URIS_, {
|
||||||
|
'Data': ol.xml.makeChildAppender(ol.format.KML.writeDataNode_),
|
||||||
|
'value': ol.xml.makeChildAppender(ol.format.KML.writeDataNodeValue_),
|
||||||
|
'displayName': ol.xml.makeChildAppender(ol.format.KML.writeDataNodeName_)
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @const
|
* @const
|
||||||
* @type {Object.<string, string>}
|
* @type {Object.<string, string>}
|
||||||
@@ -2845,6 +2939,8 @@ ol.format.KML.PLACEMARK_SEQUENCE_ = ol.xml.makeStructureNS(
|
|||||||
*/
|
*/
|
||||||
ol.format.KML.PLACEMARK_SERIALIZERS_ = ol.xml.makeStructureNS(
|
ol.format.KML.PLACEMARK_SERIALIZERS_ = ol.xml.makeStructureNS(
|
||||||
ol.format.KML.NAMESPACE_URIS_, {
|
ol.format.KML.NAMESPACE_URIS_, {
|
||||||
|
'ExtendedData': ol.xml.makeChildAppender(
|
||||||
|
ol.format.KML.writeExtendedData_),
|
||||||
'MultiGeometry': ol.xml.makeChildAppender(
|
'MultiGeometry': ol.xml.makeChildAppender(
|
||||||
ol.format.KML.writeMultiGeometry_),
|
ol.format.KML.writeMultiGeometry_),
|
||||||
'LineString': ol.xml.makeChildAppender(
|
'LineString': ol.xml.makeChildAppender(
|
||||||
@@ -3000,6 +3096,26 @@ ol.format.KML.COORDINATES_NODE_FACTORY_ =
|
|||||||
ol.xml.makeSimpleNodeFactory('coordinates');
|
ol.xml.makeSimpleNodeFactory('coordinates');
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A factory for creating Data nodes.
|
||||||
|
* @const
|
||||||
|
* @type {function(*, Array.<*>): (Node|undefined)}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
ol.format.KML.DATA_NODE_FACTORY_ =
|
||||||
|
ol.xml.makeSimpleNodeFactory('Data');
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A factory for creating ExtendedData nodes.
|
||||||
|
* @const
|
||||||
|
* @type {function(*, Array.<*>): (Node|undefined)}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
ol.format.KML.EXTENDEDDATA_NODE_FACTORY_ =
|
||||||
|
ol.xml.makeSimpleNodeFactory('ExtendedData');
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A factory for creating innerBoundaryIs nodes.
|
* A factory for creating innerBoundaryIs nodes.
|
||||||
* @const
|
* @const
|
||||||
|
|||||||
@@ -114,6 +114,15 @@ ol.format.XSD.writeBooleanTextNode = function(node, bool) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Node} node Node to append a CDATA Section with the string to.
|
||||||
|
* @param {string} string String.
|
||||||
|
*/
|
||||||
|
ol.format.XSD.writeCDATASection = function(node, string) {
|
||||||
|
node.appendChild(ol.xml.DOCUMENT.createCDATASection(string));
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Node} node Node to append a TextNode with the dateTime to.
|
* @param {Node} node Node to append a TextNode with the dateTime to.
|
||||||
* @param {number} dateTime DateTime in seconds.
|
* @param {number} dateTime DateTime in seconds.
|
||||||
|
|||||||
@@ -1488,6 +1488,83 @@ describe('ol.format.KML', function() {
|
|||||||
|
|
||||||
describe('extended data', function() {
|
describe('extended data', function() {
|
||||||
|
|
||||||
|
it('can write ExtendedData with no values', function() {
|
||||||
|
var feature = new ol.Feature();
|
||||||
|
feature.set('foo', null);
|
||||||
|
feature.set('bar', undefined);
|
||||||
|
var features = [feature];
|
||||||
|
var node = format.writeFeaturesNode(features);
|
||||||
|
var text =
|
||||||
|
'<kml xmlns="http://www.opengis.net/kml/2.2"' +
|
||||||
|
' xmlns:gx="http://www.google.com/kml/ext/2.2"' +
|
||||||
|
' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"' +
|
||||||
|
' xsi:schemaLocation="http://www.opengis.net/kml/2.2' +
|
||||||
|
' https://developers.google.com/kml/schema/kml22gx.xsd">' +
|
||||||
|
' <Placemark>' +
|
||||||
|
' <ExtendedData>' +
|
||||||
|
' <Data name="bar"/>' +
|
||||||
|
' <Data name="foo"/>' +
|
||||||
|
' </ExtendedData>' +
|
||||||
|
' </Placemark>' +
|
||||||
|
'</kml>';
|
||||||
|
expect(node).to.xmleql(ol.xml.parse(text));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can write ExtendedData with values', function() {
|
||||||
|
var feature = new ol.Feature();
|
||||||
|
feature.set('foo', 'bar');
|
||||||
|
feature.set('aNumber', 1000);
|
||||||
|
var features = [feature];
|
||||||
|
var node = format.writeFeaturesNode(features);
|
||||||
|
var text =
|
||||||
|
'<kml xmlns="http://www.opengis.net/kml/2.2"' +
|
||||||
|
' xmlns:gx="http://www.google.com/kml/ext/2.2"' +
|
||||||
|
' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"' +
|
||||||
|
' xsi:schemaLocation="http://www.opengis.net/kml/2.2' +
|
||||||
|
' https://developers.google.com/kml/schema/kml22gx.xsd">' +
|
||||||
|
' <Placemark>' +
|
||||||
|
' <ExtendedData>' +
|
||||||
|
' <Data name="aNumber">' +
|
||||||
|
' <value>1000</value>' +
|
||||||
|
' </Data>' +
|
||||||
|
' <Data name="foo">' +
|
||||||
|
' <value>bar</value>' +
|
||||||
|
' </Data>' +
|
||||||
|
' </ExtendedData>' +
|
||||||
|
' </Placemark>' +
|
||||||
|
'</kml>';
|
||||||
|
expect(node).to.xmleql(ol.xml.parse(text));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can write ExtendedData pair with displayName and value', function() {
|
||||||
|
var pair = {
|
||||||
|
value: 'bar',
|
||||||
|
displayName: 'display name'
|
||||||
|
};
|
||||||
|
|
||||||
|
var feature = new ol.Feature();
|
||||||
|
feature.set('foo', pair);
|
||||||
|
|
||||||
|
var features = [feature];
|
||||||
|
var node = format.writeFeaturesNode(features);
|
||||||
|
var text =
|
||||||
|
'<kml xmlns="http://www.opengis.net/kml/2.2"' +
|
||||||
|
' xmlns:gx="http://www.google.com/kml/ext/2.2"' +
|
||||||
|
' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"' +
|
||||||
|
' xsi:schemaLocation="http://www.opengis.net/kml/2.2' +
|
||||||
|
' https://developers.google.com/kml/schema/kml22gx.xsd">' +
|
||||||
|
' <Placemark>' +
|
||||||
|
' <ExtendedData>' +
|
||||||
|
' <Data name="foo">' +
|
||||||
|
' <displayName><![CDATA[display name]]></displayName>' +
|
||||||
|
' <value>bar</value>' +
|
||||||
|
' </Data>' +
|
||||||
|
' </ExtendedData>' +
|
||||||
|
' </Placemark>' +
|
||||||
|
'</kml>';
|
||||||
|
expect(node).to.xmleql(ol.xml.parse(text));
|
||||||
|
});
|
||||||
|
|
||||||
it('can read ExtendedData', function() {
|
it('can read ExtendedData', function() {
|
||||||
var text =
|
var text =
|
||||||
'<kml xmlns="http://earth.google.com/kml/2.2">' +
|
'<kml xmlns="http://earth.google.com/kml/2.2">' +
|
||||||
|
|||||||
Reference in New Issue
Block a user