Add parser for OGC Filter 1.0 and 1.1 (read/write)

This work is based on the ol.expr package by @tschaub.
It adds a few named expression functions to that package:

 * INTERSECTS, CONTAINS, DWITHIN, WITHIN (no client-side implementation as yet)
 * LIKE (like comparison with wildcard, singleChar and escapeChar)
 * IEQ (case-insensitive equality)
 * INEQ (case-insensitive non-equality)

It also adds a few extra parameters to the existing EXTENT function to be able
to deserialize and serialize all info (i.e. projection and property name).

Some changes were needed for the GML parser as well:

 * createGeometry function needed to be public
 * when parsing Box (GML2) and Envelope (GML3) also parse the srsName
 * fix up writing for Box and Envelope now that bounds is an array

Also added createDocumentFragment function to the XML parser. Implementation
is similar to OpenLayers 2.

Some addtional notes on the implementation:

 * PropertyIsBetween was implemented as an ol.expr.Logical with operator
   ol.expr.LogicalOp.AND and two ol.expr.Comparison instances with operator
   ol.expr.ComparisonOp.GTE and ol.expr.ComparisonOp.LTE
 * In OGC Filter And and Or can contain more than 2 sub filters, so this
   is translated into a hierarchy of ol.expr.Logical
This commit is contained in:
Bart van den Eijnden
2013-07-01 13:46:41 +02:00
parent a7ca22dde0
commit ab40ab6208
37 changed files with 1899 additions and 39 deletions

View File

@@ -97,7 +97,14 @@ ol.expr.lib = {};
ol.expr.functions = { ol.expr.functions = {
EXTENT: 'extent', EXTENT: 'extent',
FID: 'fid', FID: 'fid',
GEOMETRY_TYPE: 'geometryType' GEOMETRY_TYPE: 'geometryType',
INTERSECTS: 'intersects',
CONTAINS: 'contains',
DWITHIN: 'dwithin',
WITHIN: 'within',
LIKE: 'like',
IEQ: 'ieq',
INEQ: 'ineq'
}; };
@@ -107,12 +114,16 @@ ol.expr.functions = {
* @param {number} maxX Maximum x-coordinate value. * @param {number} maxX Maximum x-coordinate value.
* @param {number} minY Minimum y-coordinate value. * @param {number} minY Minimum y-coordinate value.
* @param {number} maxY Maximum y-coordinate value. * @param {number} maxY Maximum y-coordinate value.
* @param {string=} opt_projection Projection of the extent.
* @param {string=} opt_attribute Name of the geometry attribute to use.
* @return {boolean} The provided extent intersects the feature's extent. * @return {boolean} The provided extent intersects the feature's extent.
* @this {ol.Feature} * @this {ol.Feature}
*/ */
ol.expr.lib[ol.expr.functions.EXTENT] = function(minX, maxX, minY, maxY) { ol.expr.lib[ol.expr.functions.EXTENT] = function(minX, maxX, minY, maxY,
opt_projection, opt_attribute) {
var intersects = false; var intersects = false;
var geometry = this.getGeometry(); var geometry = goog.isDef(opt_attribute) ?
this.getAttributes()[opt_attribute] : this.getGeometry();
if (geometry) { if (geometry) {
intersects = ol.extent.intersects(geometry.getBounds(), intersects = ol.extent.intersects(geometry.getBounds(),
[minX, maxX, minY, maxY]); [minX, maxX, minY, maxY]);
@@ -142,6 +153,75 @@ ol.expr.lib[ol.expr.functions.FID] = function(var_args) {
}; };
/**
* Determine if a feature attribute is like the provided value.
* @param {string} attribute The name of the attribute to test for.
* @param {string} value The value to test for.
* @param {string} wildCard The wildcard character to use.
* @param {string} singleChar The single character to use.
* @param {string} escapeChar The escape character to use.
* @param {boolean} matchCase Should we match case or not?
* @this {ol.Feature}
*/
ol.expr.lib[ol.expr.functions.LIKE] = function(attribute, value, wildCard,
singleChar, escapeChar, matchCase) {
if (wildCard == '.') {
throw new Error('"." is an unsupported wildCard character for ' +
'ol.filter.Comparison');
}
// set UMN MapServer defaults for unspecified parameters
wildCard = goog.isDef(wildCard) ? wildCard : '*';
singleChar = goog.isDef(singleChar) ? singleChar : '.';
escapeChar = goog.isDef(escapeChar) ? escapeChar : '!';
var val;
val = value.replace(
new RegExp('\\' + escapeChar + '(.|$)', 'g'), '\\$1');
val = value.replace(
new RegExp('\\' + singleChar, 'g'), '.');
val = value.replace(
new RegExp('\\' + wildCard, 'g'), '.*');
val = value.replace(
new RegExp('\\\\.\\*', 'g'), '\\' + wildCard);
val = value.replace(
new RegExp('\\\\\\.', 'g'), '\\' + singleChar);
var attributes = this.getAttributes();
var modifiers = (matchCase === false) ? 'gi' : 'g';
return new RegExp(val, modifiers).test(attributes[attribute]);
};
/**
* Case insensitive comparison for equality.
* @param {string} attribute Name of the attribute.
* @param {string} value Value to test for equality.
* @this {ol.Feature}
*/
ol.expr.lib[ol.expr.functions.IEQ] = function(attribute, value) {
var attributes = this.getAttributes();
if (goog.isString(value) && goog.isString(attributes[attribute])) {
return value.toUpperCase() == attributes[attribute].toUpperCase();
} else {
return value == attributes[attribute];
}
};
/**
* Case insensitive comparison for non-equality.
* @param {string} attribute Name of the attribute.
* @param {string} value Value to test for non-equality.
* @this {ol.Feature}
*/
ol.expr.lib[ol.expr.functions.INEQ] = function(attribute, value) {
var attributes = this.getAttributes();
if (goog.isString(value) && goog.isString(attributes[attribute])) {
return value.toUpperCase() == attributes[attribute].toUpperCase();
} else {
return value != attributes[attribute];
}
};
/** /**
* Determine if a feature's default geometry is of the given type. * Determine if a feature's default geometry is of the given type.
* @param {ol.geom.GeometryType} type Geometry type. * @param {ol.geom.GeometryType} type Geometry type.
@@ -156,3 +236,31 @@ ol.expr.lib[ol.expr.functions.GEOMETRY_TYPE] = function(type) {
} }
return same; return same;
}; };
ol.expr.lib[ol.expr.functions.INTERSECTS] = function(geom, opt_projection,
opt_attribute) {
throw new Error('Spatial function not implemented: ' +
ol.expr.functions.INTERSECTS);
};
ol.expr.lib[ol.expr.functions.WITHIN] = function(geom, opt_projection,
opt_attribute) {
throw new Error('Spatial function not implemented: ' +
ol.expr.functions.WITHIN);
};
ol.expr.lib[ol.expr.functions.CONTAINS] = function(geom, opt_projeciton,
opt_attribute) {
throw new Error('Spatial function not implemented: ' +
ol.expr.functions.CONTAINS);
};
ol.expr.lib[ol.expr.functions.DWITHIN] = function(geom, distance, units,
opt_projection, opt_attribute) {
throw new Error('Spatial function not implemented: ' +
ol.expr.functions.DWITHIN);
};

View File

@@ -0,0 +1,37 @@
goog.provide('ol.parser.ogc.Filter');
goog.require('ol.parser.ogc.Filter_v1_0_0');
goog.require('ol.parser.ogc.Filter_v1_1_0');
goog.require('ol.parser.ogc.Versioned');
/**
* @define {boolean} Whether to enable OGC Filter version 1.0.0.
*/
ol.ENABLE_OGCFILTER_1_0_0 = true;
/**
* @define {boolean} Whether to enable OGC Filter version 1.1.0.
*/
ol.ENABLE_OGCFILTER_1_1_0 = true;
/**
* @constructor
* @param {Object=} opt_options Options which will be set on this object.
* @extends {ol.parser.ogc.Versioned}
*/
ol.parser.ogc.Filter = function(opt_options) {
opt_options = opt_options || {};
opt_options['defaultVersion'] = '1.0.0';
this.parsers = {};
if (ol.ENABLE_OGCFILTER_1_0_0) {
this.parsers['v1_0_0'] = ol.parser.ogc.Filter_v1_0_0;
}
if (ol.ENABLE_OGCFILTER_1_1_0) {
this.parsers['v1_1_0'] = ol.parser.ogc.Filter_v1_1_0;
}
goog.base(this, opt_options);
};
goog.inherits(ol.parser.ogc.Filter, ol.parser.ogc.Versioned);

View File

@@ -0,0 +1,582 @@
goog.provide('ol.parser.ogc.Filter_v1');
goog.require('goog.array');
goog.require('goog.dom.xml');
goog.require('goog.string');
goog.require('ol.expr');
goog.require('ol.expr.Call');
goog.require('ol.expr.Comparison');
goog.require('ol.expr.ComparisonOp');
goog.require('ol.expr.Identifier');
goog.require('ol.expr.Logical');
goog.require('ol.expr.LogicalOp');
goog.require('ol.expr.Not');
goog.require('ol.expr.functions');
goog.require('ol.parser.XML');
/**
* @constructor
* @extends {ol.parser.XML}
*/
ol.parser.ogc.Filter_v1 = function() {
this.defaultNamespaceURI = 'http://www.opengis.net/ogc';
this.errorProperty = 'filter';
this.readers = {
'http://www.opengis.net/ogc': {
'_expression': function(node) {
// only the simplest of ogc:expression handled
// "some text and an <PropertyName>attribute</PropertyName>"
var obj, value = '';
for (var child = node.firstChild; child; child = child.nextSibling) {
switch (child.nodeType) {
case 1:
obj = this.readNode(child);
if (obj['property']) {
value += obj['property'];
} else if (goog.isDef(obj['value'])) {
value += obj['value'];
}
break;
case 3: // text node
case 4: // cdata section
value += child.nodeValue;
break;
default:
break;
}
}
return value;
},
'Filter': function(node, obj) {
var container = {
'filters': []
};
this.readChildNodes(node, container);
if (goog.isDef(container['fids'])) {
obj['filter'] = new ol.expr.Call(
new ol.expr.Identifier(ol.expr.functions.FID),
container['fids']);
} else if (container['filters'].length > 0) {
obj['filter'] = container['filters'][0];
}
},
'FeatureId': function(node, obj) {
var fid = node.getAttribute('fid');
if (fid) {
if (!goog.isDef(obj['fids'])) {
obj['fids'] = {};
}
obj['fids'][fid] = true;
}
},
'And': function(node, obj) {
var container = {'filters': []};
this.readChildNodes(node, container);
var filter = this.aggregateLogical_(container['filters'],
ol.expr.LogicalOp.AND);
obj['filters'].push(filter);
},
'Or': function(node, obj) {
var container = {'filters': []};
this.readChildNodes(node, container);
var filter = this.aggregateLogical_(container['filters'],
ol.expr.LogicalOp.OR);
obj['filters'].push(filter);
},
'Not': function(node, obj) {
var container = {'filters': []};
this.readChildNodes(node, container);
// Not is unary so can only contain 1 child filter
obj['filters'].push(new ol.expr.Not(
container.filters[0]));
},
'PropertyIsNull': function(node, obj) {
var container = {};
this.readChildNodes(node, container);
obj['filters'].push(new ol.expr.Comparison(
ol.expr.ComparisonOp.EQ,
container['property'],
null));
},
'PropertyIsLessThan': function(node, obj) {
var container = {};
this.readChildNodes(node, container);
obj['filters'].push(new ol.expr.Comparison(
ol.expr.ComparisonOp.LT,
container['property'],
container['value']));
},
'PropertyIsGreaterThan': function(node, obj) {
var container = {};
this.readChildNodes(node, container);
obj['filters'].push(new ol.expr.Comparison(
ol.expr.ComparisonOp.GT,
container['property'],
container['value']));
},
'PropertyIsLessThanOrEqualTo': function(node, obj) {
var container = {};
this.readChildNodes(node, container);
obj['filters'].push(new ol.expr.Comparison(
ol.expr.ComparisonOp.LTE,
container['property'],
container['value']));
},
'PropertyIsGreaterThanOrEqualTo': function(node, obj) {
var container = {};
this.readChildNodes(node, container);
obj['filters'].push(new ol.expr.Comparison(
ol.expr.ComparisonOp.GTE,
container['property'],
container['value']));
},
'PropertyIsBetween': function(node, obj) {
var container = {};
this.readChildNodes(node, container);
obj['filters'].push(new ol.expr.Logical(ol.expr.LogicalOp.AND,
new ol.expr.Comparison(ol.expr.ComparisonOp.GTE,
container['property'], container['lowerBoundary']),
new ol.expr.Comparison(ol.expr.ComparisonOp.LTE,
container['property'], container['upperBoundary'])));
},
'Literal': function(node, obj) {
var nodeValue = this.getChildValue(node);
var value = goog.string.toNumber(nodeValue);
obj['value'] = isNaN(value) ? nodeValue : value;
},
'PropertyName': function(node, obj) {
obj['property'] = this.getChildValue(node);
},
'LowerBoundary': function(node, obj) {
var readers = this.readers[this.defaultNamespaceURI];
obj['lowerBoundary'] = goog.string.toNumber(
readers['_expression'].call(this, node));
},
'UpperBoundary': function(node, obj) {
var readers = this.readers[this.defaultNamespaceURI];
obj['upperBoundary'] = goog.string.toNumber(
readers['_expression'].call(this, node));
},
'_spatial': function(node, obj, identifier) {
var args = [], container = {};
this.readChildNodes(node, container);
if (goog.isDef(container.geometry)) {
args.push(this.gml_.createGeometry(container));
} else {
args = container['bounds'];
}
if (goog.isDef(container['distance'])) {
args.push(container['distance']);
}
if (goog.isDef(container['distanceUnits'])) {
args.push(container['distanceUnits']);
}
args.push(container['projection']);
if (goog.isDef(container['property'])) {
args.push(container['property']);
}
obj['filters'].push(new ol.expr.Call(new ol.expr.Identifier(
identifier), args));
},
'BBOX': function(node, obj) {
var readers = this.readers[this.defaultNamespaceURI];
readers['_spatial'].call(this, node, obj,
ol.expr.functions.EXTENT);
},
'Intersects': function(node, obj) {
var readers = this.readers[this.defaultNamespaceURI];
readers['_spatial'].call(this, node, obj,
ol.expr.functions.INTERSECTS);
},
'Within': function(node, obj) {
var readers = this.readers[this.defaultNamespaceURI];
readers['_spatial'].call(this, node, obj,
ol.expr.functions.WITHIN);
},
'Contains': function(node, obj) {
var readers = this.readers[this.defaultNamespaceURI];
readers['_spatial'].call(this, node, obj,
ol.expr.functions.CONTAINS);
},
'DWithin': function(node, obj) {
var readers = this.readers[this.defaultNamespaceURI];
readers['_spatial'].call(this, node, obj,
ol.expr.functions.DWITHIN);
},
'Distance': function(node, obj) {
obj['distance'] = parseInt(this.getChildValue(node), 10);
obj['distanceUnits'] = node.getAttribute('units');
}
}
};
this.writers = {
'http://www.opengis.net/ogc': {
'Filter': function(filter) {
var node = this.createElementNS('ogc:Filter');
this.writeNode(this.getFilterType_(filter), filter, null, node);
return node;
},
'_featureIds': function(filter) {
var node = this.createDocumentFragment();
var fids = filter.getArgs();
for (var i = 0, ii = fids.length; i < ii; i++) {
this.writeNode('FeatureId', fids[i], null, node);
}
return node;
},
'FeatureId': function(fid) {
var node = this.createElementNS('ogc:FeatureId');
node.setAttribute('fid', fid);
return node;
},
'And': function(filter) {
var node = this.createElementNS('ogc:And');
var subFilters = [];
this.getSubfiltersForLogical_(filter, subFilters);
for (var i = 0, ii = subFilters.length; i < ii; ++i) {
var subFilter = subFilters[i];
if (goog.isDefAndNotNull(subFilter)) {
this.writeNode(this.getFilterType_(subFilter), subFilter,
null, node);
}
}
return node;
},
'Or': function(filter) {
var node = this.createElementNS('ogc:Or');
var subFilters = [];
this.getSubfiltersForLogical_(filter, subFilters);
for (var i = 0, ii = subFilters.length; i < ii; ++i) {
var subFilter = subFilters[i];
if (goog.isDefAndNotNull(subFilter)) {
this.writeNode(this.getFilterType_(subFilter), subFilter,
null, node);
}
}
return node;
},
'Not': function(filter) {
var node = this.createElementNS('ogc:Not');
var childFilter = filter.getArgument();
this.writeNode(this.getFilterType_(childFilter), childFilter, null,
node);
return node;
},
'PropertyIsLessThan': function(filter) {
var node = this.createElementNS('ogc:PropertyIsLessThan');
this.writeNode('PropertyName', filter.getLeft(), null, node);
this.writeOgcExpression(filter.getRight(), node);
return node;
},
'PropertyIsGreaterThan': function(filter) {
var node = this.createElementNS('ogc:PropertyIsGreaterThan');
this.writeNode('PropertyName', filter.getLeft(), null, node);
this.writeOgcExpression(filter.getRight(), node);
return node;
},
'PropertyIsLessThanOrEqualTo': function(filter) {
var node = this.createElementNS('ogc:PropertyIsLessThanOrEqualTo');
this.writeNode('PropertyName', filter.getLeft(), null, node);
this.writeOgcExpression(filter.getRight(), node);
return node;
},
'PropertyIsGreaterThanOrEqualTo': function(filter) {
var node = this.createElementNS('ogc:PropertyIsGreaterThanOrEqualTo');
this.writeNode('PropertyName', filter.getLeft(), null, node);
this.writeOgcExpression(filter.getRight(), node);
return node;
},
'PropertyIsBetween': function(filter) {
var node = this.createElementNS('ogc:PropertyIsBetween');
var property = filter.getLeft().getLeft();
this.writeNode('PropertyName', property, null, node);
var lower, upper;
var filters = new Array(2);
filters[0] = filter.getLeft();
filters[1] = filter.getRight();
for (var i = 0; i < 2; ++i) {
var value = filters[i].getRight();
if (filters[i].getOperator() === ol.expr.ComparisonOp.GTE) {
lower = value;
} else if (filters[i].getOperator() === ol.expr.ComparisonOp.LTE) {
upper = value;
}
}
this.writeNode('LowerBoundary', lower, null, node);
this.writeNode('UpperBoundary', upper, null, node);
return node;
},
'PropertyName': function(name) {
var node = this.createElementNS('ogc:PropertyName');
node.appendChild(this.createTextNode(name));
return node;
},
'Literal': function(value) {
if (value instanceof Date) {
value = value.toISOString();
}
var node = this.createElementNS('ogc:Literal');
node.appendChild(this.createTextNode(value));
return node;
},
'LowerBoundary': function(value) {
var node = this.createElementNS('ogc:LowerBoundary');
this.writeOgcExpression(value, node);
return node;
},
'UpperBoundary': function(value) {
var node = this.createElementNS('ogc:UpperBoundary');
this.writeOgcExpression(value, node);
return node;
},
'INTERSECTS': function(filter) {
return this.writeSpatial_(filter, 'Intersects');
},
'WITHIN': function(filter) {
return this.writeSpatial_(filter, 'Within');
},
'CONTAINS': function(filter) {
return this.writeSpatial_(filter, 'Contains');
},
'DWITHIN': function(filter) {
var node = this.writeSpatial_(filter, 'DWithin');
this.writeNode('Distance', filter, null, node);
return node;
},
'Distance': function(filter) {
var node = this.createElementNS('ogc:Distance');
var args = filter.getArgs();
node.setAttribute('units', args[2]);
node.appendChild(this.createTextNode(args[1]));
return node;
},
'Function': function(filter) {
var node = this.createElementNS('ogc:Function');
node.setAttribute('name', filter.getCallee().getName());
var params = filter.getArgs();
for (var i = 0, len = params.length; i < len; i++) {
this.writeOgcExpression(params[i], node);
}
return node;
},
'PropertyIsNull': function(filter) {
var node = this.createElementNS('ogc:PropertyIsNull');
this.writeNode('PropertyName', filter.getLeft(), null, node);
return node;
}
}
};
this.filterMap_ = {
'&&': 'And',
'||': 'Or',
'!': 'Not',
'==': 'PropertyIsEqualTo',
'!=': 'PropertyIsNotEqualTo',
'<': 'PropertyIsLessThan',
'>': 'PropertyIsGreaterThan',
'<=': 'PropertyIsLessThanOrEqualTo',
'>=': 'PropertyIsGreaterThanOrEqualTo',
'..': 'PropertyIsBetween',
'~': 'PropertyIsLike',
'NULL': 'PropertyIsNull',
'BBOX': 'BBOX',
'DWITHIN': 'DWITHIN',
'WITHIN': 'WITHIN',
'CONTAINS': 'CONTAINS',
'INTERSECTS': 'INTERSECTS',
'FID': '_featureIds'
};
goog.base(this);
};
goog.inherits(ol.parser.ogc.Filter_v1, ol.parser.XML);
/**
* @param {ol.expr.Expression} filter The filter to determine the type of.
* @return {string} The type of filter.
* @private
*/
ol.parser.ogc.Filter_v1.prototype.getFilterType_ = function(filter) {
var type;
if (filter instanceof ol.expr.Logical ||
filter instanceof ol.expr.Comparison) {
type = filter.getOperator();
var isNull = (type === ol.expr.ComparisonOp.EQ &&
filter.getRight() === null);
if (isNull) {
type = 'NULL';
}
var isBetween = (type === ol.expr.LogicalOp.AND &&
filter.getLeft() instanceof ol.expr.Comparison &&
filter.getRight() instanceof ol.expr.Comparison &&
filter.getLeft().getLeft() === filter.getRight().getLeft() &&
(filter.getLeft().getOperator() === ol.expr.ComparisonOp.LTE ||
filter.getLeft().getOperator() === ol.expr.ComparisonOp.GTE) &&
(filter.getRight().getOperator() === ol.expr.ComparisonOp.LTE ||
filter.getRight().getOperator() === ol.expr.ComparisonOp.GTE));
if (isBetween) {
type = '..';
}
} else if (filter instanceof ol.expr.Call) {
var callee = filter.getCallee().getName();
if (callee === ol.expr.functions.FID) {
type = 'FID';
}
else if (callee === ol.expr.functions.IEQ) {
type = '==';
} else if (callee === ol.expr.functions.INEQ) {
type = '!=';
}
else if (callee === ol.expr.functions.LIKE) {
type = '~';
}
else if (callee === ol.expr.functions.CONTAINS) {
type = 'CONTAINS';
} else if (callee === ol.expr.functions.WITHIN) {
type = 'WITHIN';
} else if (callee === ol.expr.functions.DWITHIN) {
type = 'DWITHIN';
} else if (callee === ol.expr.functions.EXTENT) {
type = 'BBOX';
} else if (callee === ol.expr.functions.INTERSECTS) {
type = 'INTERSECTS';
}
} else if (filter instanceof ol.expr.Not) {
type = '!';
}
var filterType = this.filterMap_[type];
if (!filterType) {
throw new Error('Filter writing not supported for rule type: ' + type);
}
return filterType;
};
/**
* @param {string|Document|Element} data Data to read.
* @return {Object} An object representing the document.
*/
ol.parser.ogc.Filter_v1.prototype.read = function(data) {
if (goog.isString(data)) {
data = goog.dom.xml.loadXml(data);
}
if (data && data.nodeType == 9) {
data = data.documentElement;
}
var obj = {};
this.readNode(data, obj);
return obj['filter'];
};
/**
* @param {ol.expr.Expression} filter The filter to write out.
* @return {string} The serialized filter.
*/
ol.parser.ogc.Filter_v1.prototype.write = function(filter) {
var root = this.writeNode('Filter', filter);
this.setAttributeNS(
root, 'http://www.w3.org/2001/XMLSchema-instance',
'xsi:schemaLocation', this.schemaLocation);
return this.serialize(root);
};
/**
* @param {ol.expr.Call|string|number} value The value write out.
* @param {Element} node The node to append to.
* @return {Element} The node to which was appended.
* @protected
*/
ol.parser.ogc.Filter_v1.prototype.writeOgcExpression = function(value, node) {
if (value instanceof ol.expr.Call) {
this.writeNode('Function', value, null, node);
} else {
this.writeNode('Literal', value, null, node);
}
return node;
};
/**
* @param {ol.expr.Logical} filter The filter to retrieve the sub filters from.
* @param {Array.<ol.expr.Expression>} subFilters The sub filters retrieved.
* @private
*/
ol.parser.ogc.Filter_v1.prototype.getSubfiltersForLogical_ = function(filter,
subFilters) {
var operator = filter.getOperator();
var filters = new Array(2);
filters[0] = filter.getLeft();
filters[1] = filter.getRight();
for (var i = 0; i < 2; ++i) {
if (filters[i] instanceof ol.expr.Logical && filters[i].getOperator() ===
operator) {
this.getSubfiltersForLogical_(filters[i], subFilters);
} else {
subFilters.push(filters[i]);
}
}
};
/**
* Since ol.expr.Logical can only have a left and a right, we need to nest
* sub filters coming from OGC Filter.
* @param {Array.<ol.expr.Expression>} filters The filters to aggregate.
* @param {ol.expr.LogicalOp} operator The logical operator to use.
* @return {ol.expr.Logical} The logical filter created.
* @private
*/
ol.parser.ogc.Filter_v1.prototype.aggregateLogical_ = function(filters,
operator) {
var subFilters = [];
var newFilters = [];
// we only need to do this if we have more than 2 items
if (filters.length > 2) {
while (filters.length) {
subFilters.push(filters.pop());
if (subFilters.length === 2) {
newFilters.push(new ol.expr.Logical(operator,
subFilters[0], subFilters[1]));
goog.array.clear(subFilters);
}
}
// there could be a single item left now
if (subFilters.length === 1) {
newFilters.push(subFilters[0]);
}
return this.aggregateLogical_(newFilters, operator);
} else {
return new ol.expr.Logical(operator, filters[0], filters[1]);
}
};
/**
* @param {ol.parser.ogc.GML_v2|ol.parser.ogc.GML_v3} gml The GML parser to
* use.
* @protected
*/
ol.parser.ogc.Filter_v1.prototype.setGmlParser = function(gml) {
this.gml_ = gml;
for (var uri in this.gml_.readers) {
for (var key in this.gml_.readers[uri]) {
if (!goog.isDef(this.readers[uri])) {
this.readers[uri] = {};
}
this.readers[uri][key] = goog.bind(this.gml_.readers[uri][key],
this.gml_);
}
}
for (uri in this.gml_.writers) {
for (key in this.gml_.writers[uri]) {
if (!goog.isDef(this.writers[uri])) {
this.writers[uri] = {};
}
this.writers[uri][key] = goog.bind(this.gml_.writers[uri][key],
this.gml_);
}
}
};

View File

@@ -0,0 +1,167 @@
goog.provide('ol.parser.ogc.Filter_v1_0_0');
goog.require('goog.object');
goog.require('ol.expr');
goog.require('ol.expr.Call');
goog.require('ol.expr.Comparison');
goog.require('ol.expr.ComparisonOp');
goog.require('ol.expr.Identifier');
goog.require('ol.expr.functions');
goog.require('ol.geom.Geometry');
goog.require('ol.parser.ogc.Filter_v1');
goog.require('ol.parser.ogc.GML_v2');
/**
* @constructor
* @extends {ol.parser.ogc.Filter_v1}
*/
ol.parser.ogc.Filter_v1_0_0 = function() {
goog.base(this);
this.version = '1.0.0';
this.schemaLocation = 'http://www.opengis.net/ogc ' +
'http://schemas.opengis.net/filter/1.0.0/filter.xsd';
goog.object.extend(this.readers['http://www.opengis.net/ogc'], {
'PropertyIsEqualTo': function(node, obj) {
var container = {};
this.readChildNodes(node, container);
obj['filters'].push(new ol.expr.Comparison(
ol.expr.ComparisonOp.EQ,
container['property'],
container['value']));
},
'PropertyIsNotEqualTo': function(node, obj) {
var container = {};
this.readChildNodes(node, container);
obj['filters'].push(new ol.expr.Comparison(
ol.expr.ComparisonOp.NEQ,
container['property'],
container['value']));
},
'PropertyIsLike': function(node, obj) {
var container = {};
this.readChildNodes(node, container);
var args = [];
args.push(container['property'], container['value'],
node.getAttribute('wildCard'),
node.getAttribute('singleChar'),
node.getAttribute('escape')
);
obj['filters'].push(new ol.expr.Call(
new ol.expr.Identifier(ol.expr.functions.LIKE), args));
}
});
goog.object.extend(this.writers['http://www.opengis.net/ogc'], {
'PropertyIsEqualTo': function(filter) {
var node = this.createElementNS('ogc:PropertyIsEqualTo');
var property = filter.getLeft();
if (goog.isDef(property)) {
this.writeNode('PropertyName', property, null, node);
}
this.writeOgcExpression(filter.getRight(), node);
return node;
},
'PropertyIsNotEqualTo': function(filter) {
var node = this.createElementNS('ogc:PropertyIsNotEqualTo');
var property = filter.getLeft();
if (goog.isDef(property)) {
this.writeNode('PropertyName', property, null, node);
}
this.writeOgcExpression(filter.getRight(), node);
return node;
},
'PropertyIsLike': function(filter) {
var node = this.createElementNS('ogc:PropertyIsLike');
var args = filter.getArgs();
node.setAttribute('wildCard', args[2]);
node.setAttribute('singleChar', args[3]);
node.setAttribute('escape', args[4]);
var property = args[0];
if (goog.isDef(property)) {
this.writeNode('PropertyName', property, null, node);
}
this.writeNode('Literal', args[1], null, node);
return node;
},
'BBOX': function(filter) {
var node = this.createElementNS('ogc:BBOX');
var args = filter.getArgs();
var property = args[5], bbox = [args[0], args[1], args[2], args[3]],
projection = args[4];
// PropertyName is mandatory in 1.0.0, but e.g. GeoServer also
// accepts filters without it.
if (goog.isDefAndNotNull(property)) {
this.writeNode('PropertyName', property, null, node);
}
var box = this.writeNode('Box', bbox,
'http://www.opengis.net/gml');
if (goog.isDefAndNotNull(projection)) {
box.setAttribute('srsName', projection);
}
node.appendChild(box);
return node;
}
});
this.setGmlParser(new ol.parser.ogc.GML_v2({featureNS: 'http://foo'}));
};
goog.inherits(ol.parser.ogc.Filter_v1_0_0,
ol.parser.ogc.Filter_v1);
/**
* @param {ol.expr.Call} filter The filter to write out.
* @param {string} name The name of the spatial operator.
* @return {Element} The node created.
* @private
*/
ol.parser.ogc.Filter_v1_0_0.prototype.writeSpatial_ = function(filter, name) {
var node = this.createElementNS('ogc:' + name);
var args = filter.getArgs();
var property, geom = null, bbox, call, projection;
if (goog.isNumber(args[0])) {
bbox = [args[0], args[1], args[2], args[3]];
projection = args[4];
property = args[5];
} else if (args[0] instanceof ol.geom.Geometry) {
geom = args[0];
if (name === 'DWithin') {
projection = args[3];
property = args[4];
} else {
projection = args[1];
property = args[2];
}
} else if (args[0] instanceof ol.expr.Call) {
call = args[0];
if (name === 'DWithin') {
projection = args[3];
property = args[4];
} else {
projection = args[1];
property = args[2];
}
}
if (goog.isDefAndNotNull(property)) {
this.writeNode('PropertyName', property, null, node);
}
if (goog.isDef(call)) {
this.writeNode('Function', call, null, node);
} else {
var child;
if (geom !== null) {
child = this.writeNode('_geometry', geom,
this.gml_.featureNS).firstChild;
} else if (bbox.length === 4) {
child = this.writeNode('Box', bbox,
'http://www.opengis.net/gml');
}
if (goog.isDef(child)) {
if (goog.isDef(projection)) {
child.setAttribute('srsName', projection);
}
node.appendChild(child);
}
}
return node;
};

View File

@@ -0,0 +1,217 @@
goog.provide('ol.parser.ogc.Filter_v1_1_0');
goog.require('goog.object');
goog.require('ol.expr');
goog.require('ol.expr.Call');
goog.require('ol.expr.Comparison');
goog.require('ol.expr.ComparisonOp');
goog.require('ol.expr.Identifier');
goog.require('ol.expr.functions');
goog.require('ol.geom.Geometry');
goog.require('ol.parser.ogc.Filter_v1');
goog.require('ol.parser.ogc.GML_v3');
/**
* @constructor
* @extends {ol.parser.ogc.Filter_v1}
*/
ol.parser.ogc.Filter_v1_1_0 = function() {
goog.base(this);
this.version = '1.1.0';
this.schemaLocation = 'http://www.opengis.net/ogc ' +
'http://schemas.opengis.net/filter/1.1.0/filter.xsd';
goog.object.extend(this.readers['http://www.opengis.net/ogc'], {
'PropertyIsEqualTo': function(node, obj) {
var matchCase = node.getAttribute('matchCase');
var container = {}, filter;
this.readChildNodes(node, container);
if (matchCase === 'false' || matchCase === '0') {
filter = new ol.expr.Call(new ol.expr.Identifier(ol.expr.functions.IEQ),
[container['property'], container['value']]);
} else {
filter = new ol.expr.Comparison(
ol.expr.ComparisonOp.EQ,
container['property'],
container['value']);
}
obj['filters'].push(filter);
},
'PropertyIsNotEqualTo': function(node, obj) {
var matchCase = node.getAttribute('matchCase');
var container = {}, filter;
this.readChildNodes(node, container);
if (matchCase === 'false' || matchCase === '0') {
filter = new ol.expr.Call(new ol.expr.Identifier(
ol.expr.functions.INEQ),
[container['property'], container['value']]);
} else {
filter = new ol.expr.Comparison(
ol.expr.ComparisonOp.NEQ,
container['property'],
container['value']);
}
obj['filters'].push(filter);
},
'PropertyIsLike': function(node, obj) {
var container = {};
this.readChildNodes(node, container);
var args = [];
args.push(container['property'], container['value'],
node.getAttribute('wildCard'),
node.getAttribute('singleChar'),
node.getAttribute('escapeChar'),
node.getAttribute('matchCase'));
obj['filters'].push(new ol.expr.Call(
new ol.expr.Identifier(ol.expr.functions.LIKE), args));
}
});
goog.object.extend(this.writers['http://www.opengis.net/ogc'], {
'PropertyIsEqualTo': function(filter) {
var node = this.createElementNS('ogc:PropertyIsEqualTo');
var property, value;
if (filter instanceof ol.expr.Call) {
var args = filter.getArgs();
property = args[0];
value = args[1];
node.setAttribute('matchCase', false);
} else {
property = filter.getLeft();
value = filter.getRight();
}
this.writeNode('PropertyName', property, null, node);
this.writeOgcExpression(value, node);
return node;
},
'PropertyIsNotEqualTo': function(filter) {
var node = this.createElementNS('ogc:PropertyIsNotEqualTo');
var property, value;
if (filter instanceof ol.expr.Call) {
var args = filter.getArgs();
property = args[0];
value = args[1];
node.setAttribute('matchCase', false);
} else {
property = filter.getLeft();
value = filter.getRight();
}
this.writeNode('PropertyName', property, null, node);
this.writeOgcExpression(value, node);
return node;
},
'PropertyIsLike': function(filter) {
var node = this.createElementNS('ogc:PropertyIsLike');
var args = filter.getArgs();
node.setAttribute('wildCard', args[2]);
node.setAttribute('singleChar', args[3]);
node.setAttribute('escapeChar', args[4]);
if (goog.isDefAndNotNull(args[5])) {
node.setAttribute('matchCase', args[5]);
}
var property = args[0];
if (goog.isDef(property)) {
this.writeNode('PropertyName', property, null, node);
}
this.writeNode('Literal', args[1], null, node);
return node;
},
'BBOX': function(filter) {
var node = this.createElementNS('ogc:BBOX');
var args = filter.getArgs();
var property = args[5], bbox = [args[0], args[1], args[2], args[3]],
projection = args[4];
// PropertyName is optional in 1.1.0
if (goog.isDefAndNotNull(property)) {
this.writeNode('PropertyName', property, null, node);
}
var box = this.writeNode('Envelope', bbox,
'http://www.opengis.net/gml');
if (goog.isDefAndNotNull(projection)) {
box.setAttribute('srsName', projection);
}
node.appendChild(box);
return node;
},
'SortBy': function(sortProperties) {
var node = this.createElementNS('ogc:SortBy');
for (var i = 0, l = sortProperties.length; i < l; i++) {
this.writeNode('SortProperty', sortProperties[i], null, node);
}
return node;
},
'SortProperty': function(sortProperty) {
var node = this.createElementNS('ogc:SortProperty');
this.writeNode('PropertyName', sortProperty['property'], null, node);
this.writeNode('SortOrder',
(sortProperty['order'] == 'DESC') ? 'DESC' : 'ASC', null, node);
return node;
},
'SortOrder': function(value) {
var node = this.createElementNS('ogc:SortOrder');
node.appendChild(this.createTextNode(value));
return node;
}
});
this.setGmlParser(new ol.parser.ogc.GML_v3());
};
goog.inherits(ol.parser.ogc.Filter_v1_1_0,
ol.parser.ogc.Filter_v1);
/**
* @param {ol.expr.Call} filter The filter to write out.
* @param {string} name The name of the spatial operator.
* @return {Element} The node created.
* @private
*/
ol.parser.ogc.Filter_v1_1_0.prototype.writeSpatial_ = function(filter, name) {
var node = this.createElementNS('ogc:' + name);
var args = filter.getArgs();
var property, geom = null, bbox, call, projection;
if (goog.isNumber(args[0])) {
bbox = [args[0], args[1], args[2], args[3]];
projection = args[4];
property = args[5];
} else if (args[0] instanceof ol.geom.Geometry) {
geom = args[0];
if (name === 'DWithin') {
projection = args[3];
property = args[4];
} else {
projection = args[1];
property = args[2];
}
} else if (args[0] instanceof ol.expr.Call) {
call = args[0];
if (name === 'DWithin') {
projection = args[3];
property = args[4];
} else {
projection = args[1];
property = args[2];
}
}
if (goog.isDefAndNotNull(property)) {
this.writeNode('PropertyName', property, null, node);
}
if (goog.isDef(call)) {
this.writeNode('Function', call, null, node);
} else {
var child;
if (geom !== null) {
child = this.writeNode('_geometry', geom,
this.gml_.featureNS).firstChild;
} else if (bbox.length === 4) {
child = this.writeNode('Envelope', bbox,
'http://www.opengis.net/gml');
}
if (goog.isDef(child)) {
if (goog.isDef(projection)) {
child.setAttribute('srsName', projection);
}
node.appendChild(child);
}
}
return node;
};

View File

@@ -284,7 +284,7 @@ ol.parser.ogc.GML = function(opt_options) {
sharedVertices = callback(feature, geom.type); sharedVertices = callback(feature, geom.type);
} }
} }
var geometry = this.createGeometry_({geometry: geom}, var geometry = this.createGeometry({geometry: geom},
sharedVertices); sharedVertices);
if (goog.isDef(geometry)) { if (goog.isDef(geometry)) {
feature.setGeometry(geometry); feature.setGeometry(geometry);
@@ -434,7 +434,7 @@ ol.parser.ogc.GML = function(opt_options) {
} else if (type === ol.geom.GeometryType.GEOMETRYCOLLECTION) { } else if (type === ol.geom.GeometryType.GEOMETRYCOLLECTION) {
child = this.writeNode('GeometryCollection', geometry, null, node); child = this.writeNode('GeometryCollection', geometry, null, node);
} }
if (goog.isDef(this.srsName)) { if (goog.isDefAndNotNull(this.srsName)) {
this.setAttributeNS(child, null, 'srsName', this.srsName); this.setAttributeNS(child, null, 'srsName', this.srsName);
} }
return node; return node;
@@ -503,13 +503,12 @@ ol.parser.ogc.GML.prototype.readNode = function(node, obj, opt_first) {
/** /**
* @private
* @param {Object} container Geometry container. * @param {Object} container Geometry container.
* @param {ol.geom.SharedVertices=} opt_vertices Shared vertices. * @param {ol.geom.SharedVertices=} opt_vertices Shared vertices.
* @return {ol.geom.Geometry} The geometry created. * @return {ol.geom.Geometry} The geometry created.
*/ */
// TODO use a mixin since this is also used in the KML parser // TODO use a mixin since this is also used in the KML parser
ol.parser.ogc.GML.prototype.createGeometry_ = function(container, ol.parser.ogc.GML.prototype.createGeometry = function(container,
opt_vertices) { opt_vertices) {
var geometry = null, coordinates, i, ii; var geometry = null, coordinates, i, ii;
switch (container.geometry.type) { switch (container.geometry.type) {
@@ -553,7 +552,7 @@ ol.parser.ogc.GML.prototype.createGeometry_ = function(container,
case ol.geom.GeometryType.GEOMETRYCOLLECTION: case ol.geom.GeometryType.GEOMETRYCOLLECTION:
var geometries = []; var geometries = [];
for (i = 0, ii = container.geometry.parts.length; i < ii; i++) { for (i = 0, ii = container.geometry.parts.length; i < ii; i++) {
geometries.push(this.createGeometry_({ geometries.push(this.createGeometry({
geometry: container.geometry.parts[i] geometry: container.geometry.parts[i]
}, opt_vertices)); }, opt_vertices));
} }

View File

@@ -29,6 +29,7 @@ ol.parser.ogc.GML_v2 = function(opt_options) {
'Box': function(node, container) { 'Box': function(node, container) {
var coordinates = []; var coordinates = [];
this.readChildNodes(node, coordinates); this.readChildNodes(node, coordinates);
container.projection = node.getAttribute('srsName');
container.bounds = [coordinates[0][0][0], coordinates[0][1][0], container.bounds = [coordinates[0][0][0], coordinates[0][1][0],
coordinates[0][0][1], coordinates[0][1][1]]; coordinates[0][0][1], coordinates[0][1][1]];
} }
@@ -90,10 +91,10 @@ ol.parser.ogc.GML_v2 = function(opt_options) {
}, },
'Box': function(extent) { 'Box': function(extent) {
var node = this.createElementNS('gml:Box'); var node = this.createElementNS('gml:Box');
this.writeNode('coordinates', [[extent.minX, extent.minY], this.writeNode('coordinates', [[extent[0], extent[1]],
[extent.maxX, extent.maxY]], null, node); [extent[2], extent[3]]], null, node);
// srsName attribute is optional for gml:Box // srsName attribute is optional for gml:Box
if (goog.isDef(this.srsName)) { if (goog.isDefAndNotNull(this.srsName)) {
node.setAttribute('srsName', this.srsName); node.setAttribute('srsName', this.srsName);
} }
return node; return node;

View File

@@ -55,7 +55,7 @@ ol.parser.ogc.GML_v3 = function(opt_options) {
} else if (type === ol.geom.GeometryType.GEOMETRYCOLLECTION) { } else if (type === ol.geom.GeometryType.GEOMETRYCOLLECTION) {
child = this.writeNode('MultiGeometry', geometry, null, node); child = this.writeNode('MultiGeometry', geometry, null, node);
} }
if (goog.isDef(this.srsName)) { if (goog.isDefAndNotNull(this.srsName)) {
this.setAttributeNS(child, null, 'srsName', this.srsName); this.setAttributeNS(child, null, 'srsName', this.srsName);
} }
return node; return node;
@@ -206,6 +206,7 @@ ol.parser.ogc.GML_v3 = function(opt_options) {
'Envelope': function(node, container) { 'Envelope': function(node, container) {
var coordinates = []; var coordinates = [];
this.readChildNodes(node, coordinates); this.readChildNodes(node, coordinates);
container.projection = node.getAttribute('srsName');
container.bounds = [coordinates[0][0][0][0], coordinates[1][0][0][0], container.bounds = [coordinates[0][0][0][0], coordinates[1][0][0][0],
coordinates[0][0][0][1], coordinates[1][0][0][1]]; coordinates[0][0][0][1], coordinates[1][0][0][1]];
}, },
@@ -374,9 +375,9 @@ ol.parser.ogc.GML_v3 = function(opt_options) {
// only 2d for simple features profile // only 2d for simple features profile
var pos; var pos;
if (this.axisOrientation.substr(0, 2) === 'en') { if (this.axisOrientation.substr(0, 2) === 'en') {
pos = (bounds.left + ' ' + bounds.bottom); pos = (bounds[0] + ' ' + bounds[2]);
} else { } else {
pos = (bounds.bottom + ' ' + bounds.left); pos = (bounds[2] + ' ' + bounds[0]);
} }
var node = this.createElementNS('gml:lowerCorner'); var node = this.createElementNS('gml:lowerCorner');
node.appendChild(this.createTextNode(pos)); node.appendChild(this.createTextNode(pos));
@@ -386,9 +387,9 @@ ol.parser.ogc.GML_v3 = function(opt_options) {
// only 2d for simple features profile // only 2d for simple features profile
var pos; var pos;
if (this.axisOrientation.substr(0, 2) === 'en') { if (this.axisOrientation.substr(0, 2) === 'en') {
pos = (bounds.right + ' ' + bounds.top); pos = (bounds[1] + ' ' + bounds[3]);
} else { } else {
pos = (bounds.top + ' ' + bounds.right); pos = (bounds[3] + ' ' + bounds[1]);
} }
var node = this.createElementNS('gml:upperCorner'); var node = this.createElementNS('gml:upperCorner');
node.appendChild(this.createTextNode(pos)); node.appendChild(this.createTextNode(pos));

View File

@@ -182,8 +182,9 @@ ol.parser.XML.prototype.createElementNS = function(name, opt_uri) {
* results to a node. * results to a node.
* *
* @param {string} name The name of a node to generate. Only use a local name. * @param {string} name The name of a node to generate. Only use a local name.
* @param {Object} obj Structure containing data for the writer. * @param {Object|string|number} obj Structure containing data for the writer.
* @param {string=} opt_uri The name space uri to which the node belongs. * @param {?string=} opt_uri The name space uri to which the node
* belongs.
* @param {Element=} opt_parent Result will be appended to this node. If no * @param {Element=} opt_parent Result will be appended to this node. If no
* parent is supplied, the node will not be appended to anything. * parent is supplied, the node will not be appended to anything.
* @return {?Element} The child node. * @return {?Element} The child node.
@@ -273,3 +274,22 @@ ol.parser.XML.prototype.serialize = function(node) {
return goog.dom.xml.serialize(node); return goog.dom.xml.serialize(node);
} }
}; };
/**
* Create a document fragment node that can be appended to another node
* created by createElementNS. This will call
* document.createDocumentFragment outside of IE. In IE, the ActiveX
* object's createDocumentFragment method is used.
*
* @return {Element} A document fragment.
*/
ol.parser.XML.prototype.createDocumentFragment = function() {
var element;
if (this.xmldom) {
element = this.xmldom.createDocumentFragment();
} else {
element = document.createDocumentFragment();
}
return element;
};

View File

@@ -0,0 +1,238 @@
goog.provide('ol.test.parser.ogc.Filter_v1_0_0');
describe('ol.parser.ogc.Filter_v1_0_0', function() {
var parser = new ol.parser.ogc.Filter_v1_0_0();
describe('#readwrite', function() {
it('intersects filter read / written correctly', function(done) {
var url = 'spec/ol/parser/ogc/xml/filter_v1_0_0/intersects.xml';
afterLoadXml(url, function(xml) {
var filter = parser.read(xml);
expect(filter instanceof ol.expr.Call).to.be(true);
expect(filter.getCallee().getName()).to.eql(
ol.expr.functions.INTERSECTS);
var args = filter.getArgs();
var geom = args[0];
expect(geom instanceof ol.geom.Polygon).to.be(true);
expect(args[2]).to.eql('Geometry');
var output = parser.write(filter);
expect(goog.dom.xml.loadXml(output)).to.xmleql(xml);
done();
});
});
it('within filter read / written correctly', function(done) {
var url = 'spec/ol/parser/ogc/xml/filter_v1_0_0/within.xml';
afterLoadXml(url, function(xml) {
var filter = parser.read(xml);
expect(filter instanceof ol.expr.Call).to.be(true);
expect(filter.getCallee().getName()).to.eql(ol.expr.functions.WITHIN);
var args = filter.getArgs();
var geom = args[0];
expect(geom instanceof ol.geom.Polygon).to.be(true);
expect(args[2]).to.eql('Geometry');
var output = parser.write(filter);
expect(goog.dom.xml.loadXml(output)).to.xmleql(xml);
done();
});
});
it('contains filter read / written correctly', function(done) {
var url = 'spec/ol/parser/ogc/xml/filter_v1_0_0/contains.xml';
afterLoadXml(url, function(xml) {
var filter = parser.read(xml);
expect(filter instanceof ol.expr.Call).to.be(true);
expect(filter.getCallee().getName()).to.eql(
ol.expr.functions.CONTAINS);
var args = filter.getArgs();
var geom = args[0];
expect(geom instanceof ol.geom.Polygon).to.be(true);
expect(args[2]).to.eql('Geometry');
var output = parser.write(filter);
expect(goog.dom.xml.loadXml(output)).to.xmleql(xml);
done();
});
});
it('between filter read / written correctly', function(done) {
var url = 'spec/ol/parser/ogc/xml/filter_v1_0_0/between.xml';
afterLoadXml(url, function(xml) {
var filter = parser.read(xml);
expect(filter instanceof ol.expr.Logical).to.be.ok();
expect(filter.getOperator()).to.eql(ol.expr.LogicalOp.AND);
expect(filter.getLeft() instanceof ol.expr.Comparison).to.be.ok();
expect(filter.getLeft().getOperator()).to.eql(ol.expr.ComparisonOp.GTE);
expect(filter.getLeft().getLeft()).to.eql('number');
expect(filter.getLeft().getRight()).to.eql(0);
expect(filter.getRight() instanceof ol.expr.Comparison).to.be.ok();
expect(filter.getRight().getOperator()).to.eql(
ol.expr.ComparisonOp.LTE);
expect(filter.getRight().getLeft()).to.eql('number');
expect(filter.getRight().getRight()).to.eql(100);
var output = parser.write(filter);
expect(goog.dom.xml.loadXml(output)).to.xmleql(xml);
done();
});
});
it('between filter read correctly without literals', function(done) {
var url = 'spec/ol/parser/ogc/xml/filter_v1_0_0/between2.xml';
afterLoadXml(url, function(xml) {
var filter = parser.read(xml);
expect(filter instanceof ol.expr.Logical).to.be.ok();
expect(filter.getOperator()).to.eql(ol.expr.LogicalOp.AND);
expect(filter.getLeft() instanceof ol.expr.Comparison).to.be.ok();
expect(filter.getLeft().getOperator()).to.eql(ol.expr.ComparisonOp.GTE);
expect(filter.getLeft().getLeft()).to.eql('number');
expect(filter.getLeft().getRight()).to.eql(0);
expect(filter.getRight() instanceof ol.expr.Comparison).to.be.ok();
expect(filter.getRight().getOperator()).to.eql(
ol.expr.ComparisonOp.LTE);
expect(filter.getRight().getLeft()).to.eql('number');
expect(filter.getRight().getRight()).to.eql(100);
done();
});
});
it('null filter read / written correctly', function(done) {
var url = 'spec/ol/parser/ogc/xml/filter_v1_0_0/null.xml';
afterLoadXml(url, function(xml) {
var filter = parser.read(xml);
expect(filter instanceof ol.expr.Comparison).to.be.ok();
expect(filter.getLeft()).to.eql('prop');
expect(filter.getRight()).to.eql(null);
var output = parser.write(filter);
expect(goog.dom.xml.loadXml(output)).to.xmleql(xml);
done();
});
});
it('BBOX written correctly', function(done) {
var url = 'spec/ol/parser/ogc/xml/filter_v1_0_0/bbox.xml';
afterLoadXml(url, function(xml) {
var filter = new ol.expr.Call(
new ol.expr.Identifier(ol.expr.functions.EXTENT),
[-180, -90, 180, 90, 'EPSG:4326', 'the_geom']);
var output = parser.write(filter);
expect(goog.dom.xml.loadXml(output)).to.xmleql(xml);
done();
});
});
it('BBOX without geometry name written correctly', function(done) {
var url = 'spec/ol/parser/ogc/xml/filter_v1_0_0/bbox_nogeom.xml';
afterLoadXml(url, function(xml) {
var filter = new ol.expr.Call(
new ol.expr.Identifier(ol.expr.functions.EXTENT),
[-180, -90, 180, 90, 'EPSG:4326']);
var output = parser.write(filter);
expect(goog.dom.xml.loadXml(output)).to.xmleql(xml);
done();
});
});
it('DWithin written correctly', function(done) {
var url = 'spec/ol/parser/ogc/xml/filter_v1_0_0/dwithin.xml';
afterLoadXml(url, function(xml) {
var filter = new ol.expr.Call(new ol.expr.Identifier(
ol.expr.functions.DWITHIN),
[new ol.geom.Point([2488789, 289552]), 1000, 'm', undefined,
'Geometry']);
var output = parser.write(filter);
expect(goog.dom.xml.loadXml(output)).to.xmleql(xml);
filter = parser.read(xml);
output = parser.write(filter);
expect(goog.dom.xml.loadXml(output)).to.xmleql(xml);
done();
});
});
});
// the Filter Encoding spec doesn't allow for FID filters inside logical
// filters however, to be liberal, we will write them without complaining
describe('#logicalfid', function() {
it('logical filter [OR] with fid filter written correctly', function(done) {
var url = 'spec/ol/parser/ogc/xml/filter_v1_0_0/logicalfeatureid.xml';
afterLoadXml(url, function(xml) {
var filter = new ol.expr.Logical(ol.expr.LogicalOp.OR,
new ol.expr.Call(new ol.expr.Identifier(ol.expr.functions.LIKE),
['person', 'me', '*', '.', '!']),
new ol.expr.Call(new ol.expr.Identifier(ol.expr.functions.FID),
['foo.1', 'foo.2']));
var output = parser.write(filter);
expect(goog.dom.xml.loadXml(output)).to.xmleql(xml);
done();
});
});
it('logical filter [AND] with fid filter written correctly',
function(done) {
var url = 'spec/ol/parser/ogc/xml/filter_v1_0_0/' +
'logicalfeatureidand.xml';
afterLoadXml(url, function(xml) {
var filter = new ol.expr.Logical(ol.expr.LogicalOp.AND,
new ol.expr.Call(new ol.expr.Identifier(ol.expr.functions.LIKE),
['person', 'me', '*', '.', '!']),
new ol.expr.Call(new ol.expr.Identifier(ol.expr.functions.FID),
['foo.1', 'foo.2']));
var output = parser.write(filter);
expect(goog.dom.xml.loadXml(output)).to.xmleql(xml);
done();
});
});
it('logical filter [NOT] with fid filter written correctly',
function(done) {
var url = 'spec/ol/parser/ogc/xml/filter_v1_0_0/' +
'logicalfeatureidnot.xml';
afterLoadXml(url, function(xml) {
var filter = new ol.expr.Not(
new ol.expr.Call(new ol.expr.Identifier(ol.expr.functions.FID),
['foo.2']));
var output = parser.write(filter);
expect(goog.dom.xml.loadXml(output)).to.xmleql(xml);
done();
});
});
});
describe('#date', function() {
it('date writing works as expected', function(done) {
var url = 'spec/ol/parser/ogc/xml/filter_v1_0_0/betweendates.xml';
afterLoadXml(url, function(xml) {
// ISO 8601: 2010-11-27T18:19:15.123Z
var start = new Date(Date.UTC(2010, 10, 27, 18, 19, 15, 123));
// ISO 8601: 2011-12-27T18:19:15.123Z
var end = new Date(Date.UTC(2011, 11, 27, 18, 19, 15, 123));
var filter = new ol.expr.Logical(ol.expr.LogicalOp.AND,
new ol.expr.Comparison(ol.expr.ComparisonOp.GTE, 'when', start),
new ol.expr.Comparison(ol.expr.ComparisonOp.LTE, 'when', end));
var output = parser.write(filter);
expect(goog.dom.xml.loadXml(output)).to.xmleql(xml);
done();
});
});
});
});
goog.require('goog.dom.xml');
goog.require('ol.expr');
goog.require('ol.expr.Call');
goog.require('ol.expr.Comparison');
goog.require('ol.expr.ComparisonOp');
goog.require('ol.expr.Identifier');
goog.require('ol.expr.Logical');
goog.require('ol.expr.LogicalOp');
goog.require('ol.expr.Not');
goog.require('ol.expr.functions');
goog.require('ol.geom.Point');
goog.require('ol.geom.Polygon');
goog.require('ol.parser.ogc.Filter_v1_0_0');

View File

@@ -0,0 +1,230 @@
goog.provide('ol.test.parser.ogc.Filter_v1_1_0');
describe('ol.parser.ogc.Filter_v1_1_0', function() {
var parser = new ol.parser.ogc.Filter_v1_1_0();
describe('#readwrite', function() {
it('filter read correctly', function(done) {
var url = 'spec/ol/parser/ogc/xml/filter_v1_1_0/test.xml';
afterLoadXml(url, function(xml) {
var filter = parser.read(xml);
expect(filter instanceof ol.expr.Logical).to.be(true);
expect(filter.getOperator()).to.eql(ol.expr.LogicalOp.OR);
var filters = [];
parser.getSubfiltersForLogical_(filter, filters);
expect(filters.length).to.eql(5);
expect(filters[0]).to.eql(new ol.expr.Logical(ol.expr.LogicalOp.AND,
new ol.expr.Comparison(
ol.expr.ComparisonOp.GTE, 'number', 1064866676),
new ol.expr.Comparison(
ol.expr.ComparisonOp.LTE, 'number', 1065512599)));
expect(filters[1]).to.eql(new ol.expr.Not(new ol.expr.Comparison(
ol.expr.ComparisonOp.LTE, 'FOO', 5000)));
expect(filters[2] instanceof ol.expr.Call).to.be(true);
expect(filters[2].getCallee().getName()).to.eql(
ol.expr.functions.LIKE);
expect(filters[2].getArgs()).to.eql(['cat', '*dog.food!*good', '*',
'.', '!', null]);
expect(filters[3] instanceof ol.expr.Call).to.be(true);
expect(filters[3].getCallee().getName()).to.eql(
ol.expr.functions.IEQ);
expect(filters[3].getArgs()).to.eql(['cat', 'dog']);
expect(filters[4] instanceof ol.expr.Comparison).to.be(true);
expect(filters[4].getOperator()).to.eql(ol.expr.ComparisonOp.EQ);
expect(filters[4].getLeft()).to.eql('cat');
expect(filters[4].getRight()).to.eql('dog');
done();
});
});
it('matchCase read correctly', function() {
var cases = [{
str:
'<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">' +
'<ogc:PropertyIsEqualTo>' +
'<ogc:PropertyName>cat</ogc:PropertyName>' +
'<ogc:Literal>dog</ogc:Literal>' +
'</ogc:PropertyIsEqualTo>' +
'</ogc:Filter>',
exp: true
}, {
str:
'<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">' +
'<ogc:PropertyIsEqualTo matchCase="1">' +
'<ogc:PropertyName>cat</ogc:PropertyName>' +
'<ogc:Literal>dog</ogc:Literal>' +
'</ogc:PropertyIsEqualTo>' +
'</ogc:Filter>',
exp: true
}, {
str:
'<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">' +
'<ogc:PropertyIsEqualTo matchCase="true">' +
'<ogc:PropertyName>cat</ogc:PropertyName>' +
'<ogc:Literal>dog</ogc:Literal>' +
'</ogc:PropertyIsEqualTo>' +
'</ogc:Filter>',
exp: true
}, {
str:
'<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">' +
'<ogc:PropertyIsEqualTo matchCase="0">' +
'<ogc:PropertyName>cat</ogc:PropertyName>' +
'<ogc:Literal>dog</ogc:Literal>' +
'</ogc:PropertyIsEqualTo>' +
'</ogc:Filter>',
exp: false
}, {
str:
'<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">' +
'<ogc:PropertyIsEqualTo matchCase="0">' +
'<ogc:PropertyName>cat</ogc:PropertyName>' +
'<ogc:Literal>dog</ogc:Literal>' +
'</ogc:PropertyIsEqualTo>' +
'</ogc:Filter>',
exp: false
}, {
str:
'<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">' +
'<ogc:PropertyIsNotEqualTo matchCase="true">' +
'<ogc:PropertyName>cat</ogc:PropertyName>' +
'<ogc:Literal>dog</ogc:Literal>' +
'</ogc:PropertyIsNotEqualTo>' +
'</ogc:Filter>',
exp: true
}, {
str:
'<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">' +
'<ogc:PropertyIsNotEqualTo matchCase="false">' +
'<ogc:PropertyName>cat</ogc:PropertyName>' +
'<ogc:Literal>dog</ogc:Literal>' +
'</ogc:PropertyIsNotEqualTo>' +
'</ogc:Filter>',
exp: false
}];
var filter, c;
for (var i = 0; i < cases.length; ++i) {
c = cases[i];
filter = parser.read(c.str);
var matchCase = (filter instanceof ol.expr.Call) ? false : true;
expect(matchCase).to.eql(c.exp);
}
});
it('BBOX filter written correctly', function(done) {
var url = 'spec/ol/parser/ogc/xml/filter_v1_1_0/bbox.xml';
afterLoadXml(url, function(xml) {
var filter = parser.read(xml);
var output = parser.write(filter);
expect(goog.dom.xml.loadXml(output)).to.xmleql(xml);
done();
});
});
it('BBOX filter without property name written correctly', function(done) {
var url = 'spec/ol/parser/ogc/xml/filter_v1_1_0/bbox_nogeomname.xml';
afterLoadXml(url, function(xml) {
var filter = parser.read(xml);
var output = parser.write(filter);
expect(goog.dom.xml.loadXml(output)).to.xmleql(xml);
done();
});
});
it('Intersects filter read / written correctly', function(done) {
var url = 'spec/ol/parser/ogc/xml/filter_v1_1_0/intersects.xml';
afterLoadXml(url, function(xml) {
var filter = parser.read(xml);
var output = parser.write(filter);
expect(goog.dom.xml.loadXml(output)).to.xmleql(xml);
done();
});
});
it('Filter functions written correctly', function(done) {
var url = 'spec/ol/parser/ogc/xml/filter_v1_1_0/function.xml';
afterLoadXml(url, function(xml) {
var filter = new ol.expr.Call(new ol.expr.Identifier(
ol.expr.functions.INTERSECTS),
[new ol.expr.Call(new ol.expr.Identifier('querySingle'),
['sf:restricted', 'the_geom',
'cat=3']), undefined, 'the_geom']);
var output = parser.write(filter);
expect(goog.dom.xml.loadXml(output)).to.xmleql(xml);
done();
});
});
it('Custom filter functions written correctly', function(done) {
var url = 'spec/ol/parser/ogc/xml/filter_v1_1_0/customfunction.xml';
afterLoadXml(url, function(xml) {
var filter = new ol.expr.Logical(ol.expr.LogicalOp.AND,
new ol.expr.Call(new ol.expr.Identifier(ol.expr.functions.INEQ),
['FOO', new ol.expr.Call(new ol.expr.Identifier('customFunction'),
['param1', 'param2'])]));
var output = parser.write(filter);
expect(goog.dom.xml.loadXml(output)).to.xmleql(xml);
done();
});
});
it('Nested filter functions written correctly', function(done) {
var url = 'spec/ol/parser/ogc/xml/filter_v1_1_0/nestedfunction.xml';
afterLoadXml(url, function(xml) {
var filter = new ol.expr.Call(new ol.expr.Identifier(
ol.expr.functions.DWITHIN),
[new ol.expr.Call(new ol.expr.Identifier('collectGeometries'),
[new ol.expr.Call(new ol.expr.Identifier('queryCollection'),
['sf:roads', 'the_geom', 'INCLUDE'])]), 200, 'meters',
undefined, 'the_geom']);
var output = parser.write(filter);
expect(goog.dom.xml.loadXml(output)).to.xmleql(xml);
done();
});
});
it('matchCase written correctly on Like filter', function(done) {
var url = 'spec/ol/parser/ogc/xml/filter_v1_1_0/likematchcase.xml';
afterLoadXml(url, function(xml) {
var filter = new ol.expr.Call(
new ol.expr.Identifier(ol.expr.functions.LIKE),
['person', '*me*', '*', '.', '!', false]);
var output = parser.write(filter);
expect(goog.dom.xml.loadXml(output)).to.xmleql(xml);
done();
});
});
it('sortBy written correctly on Like filter', function(done) {
var url = 'spec/ol/parser/ogc/xml/filter_v1_1_0/sortby.xml';
afterLoadXml(url, function(xml) {
var writer = parser.writers['http://www.opengis.net/ogc']['SortBy'];
var output = writer.call(parser, [{
'property': 'Title',
'order': 'ASC'
},{
'property': 'Relevance',
'order': 'DESC'
}]);
expect(output).to.xmleql(xml);
done();
});
});
});
});
goog.require('goog.dom.xml');
goog.require('ol.expr');
goog.require('ol.expr.Call');
goog.require('ol.expr.Comparison');
goog.require('ol.expr.ComparisonOp');
goog.require('ol.expr.Identifier');
goog.require('ol.expr.Logical');
goog.require('ol.expr.LogicalOp');
goog.require('ol.expr.Not');
goog.require('ol.expr.functions');
goog.require('ol.parser.ogc.Filter_v1_1_0');

View File

@@ -19,7 +19,7 @@ describe('ol.parser.gml_v2', function() {
afterLoadXml(url, function(xml) { afterLoadXml(url, function(xml) {
var obj = parser.read(xml); var obj = parser.read(xml);
parser.srsName = 'foo'; parser.srsName = 'foo';
var geom = parser.createGeometry_({geometry: obj.geometry}); var geom = parser.createGeometry({geometry: obj.geometry});
var node = parser.featureNSWiters_['_geometry'].apply(parser, var node = parser.featureNSWiters_['_geometry'].apply(parser,
[geom]).firstChild; [geom]).firstChild;
expect(goog.dom.xml.loadXml(parser.serialize(node))).to.xmleql(xml); expect(goog.dom.xml.loadXml(parser.serialize(node))).to.xmleql(xml);
@@ -47,7 +47,7 @@ describe('ol.parser.gml_v2', function() {
afterLoadXml(url, function(xml) { afterLoadXml(url, function(xml) {
var obj = parser.read(xml); var obj = parser.read(xml);
parser.srsName = 'foo'; parser.srsName = 'foo';
var geom = parser.createGeometry_({geometry: obj.geometry}); var geom = parser.createGeometry({geometry: obj.geometry});
var node = parser.featureNSWiters_['_geometry'].apply(parser, var node = parser.featureNSWiters_['_geometry'].apply(parser,
[geom]).firstChild; [geom]).firstChild;
expect(goog.dom.xml.loadXml(parser.serialize(node))).to.xmleql(xml); expect(goog.dom.xml.loadXml(parser.serialize(node))).to.xmleql(xml);
@@ -76,7 +76,7 @@ describe('ol.parser.gml_v2', function() {
afterLoadXml(url, function(xml) { afterLoadXml(url, function(xml) {
var obj = parser.read(xml); var obj = parser.read(xml);
parser.srsName = 'foo'; parser.srsName = 'foo';
var geom = parser.createGeometry_({geometry: obj.geometry}); var geom = parser.createGeometry({geometry: obj.geometry});
var node = parser.featureNSWiters_['_geometry'].apply(parser, var node = parser.featureNSWiters_['_geometry'].apply(parser,
[geom]).firstChild; [geom]).firstChild;
expect(goog.dom.xml.loadXml(parser.serialize(node))).to.xmleql(xml); expect(goog.dom.xml.loadXml(parser.serialize(node))).to.xmleql(xml);
@@ -104,7 +104,7 @@ describe('ol.parser.gml_v2', function() {
afterLoadXml(url, function(xml) { afterLoadXml(url, function(xml) {
var obj = parser.read(xml); var obj = parser.read(xml);
parser.srsName = 'foo'; parser.srsName = 'foo';
var geom = parser.createGeometry_({geometry: obj.geometry}); var geom = parser.createGeometry({geometry: obj.geometry});
var node = parser.featureNSWiters_['_geometry'].apply(parser, var node = parser.featureNSWiters_['_geometry'].apply(parser,
[geom]).firstChild; [geom]).firstChild;
expect(goog.dom.xml.loadXml(parser.serialize(node))).to.xmleql(xml); expect(goog.dom.xml.loadXml(parser.serialize(node))).to.xmleql(xml);
@@ -138,7 +138,7 @@ describe('ol.parser.gml_v2', function() {
afterLoadXml(url, function(xml) { afterLoadXml(url, function(xml) {
var obj = parser.read(xml); var obj = parser.read(xml);
parser.srsName = 'foo'; parser.srsName = 'foo';
var geom = parser.createGeometry_({geometry: obj.geometry}); var geom = parser.createGeometry({geometry: obj.geometry});
var node = parser.featureNSWiters_['_geometry'].apply(parser, var node = parser.featureNSWiters_['_geometry'].apply(parser,
[geom]).firstChild; [geom]).firstChild;
expect(goog.dom.xml.loadXml(parser.serialize(node))).to.xmleql(xml); expect(goog.dom.xml.loadXml(parser.serialize(node))).to.xmleql(xml);
@@ -170,7 +170,7 @@ describe('ol.parser.gml_v2', function() {
afterLoadXml(url, function(xml) { afterLoadXml(url, function(xml) {
var obj = parser.read(xml); var obj = parser.read(xml);
parser.srsName = 'foo'; parser.srsName = 'foo';
var geom = parser.createGeometry_({geometry: obj.geometry}); var geom = parser.createGeometry({geometry: obj.geometry});
var node = parser.featureNSWiters_['_geometry'].apply(parser, var node = parser.featureNSWiters_['_geometry'].apply(parser,
[geom]).firstChild; [geom]).firstChild;
expect(goog.dom.xml.loadXml(parser.serialize(node))).to.xmleql(xml); expect(goog.dom.xml.loadXml(parser.serialize(node))).to.xmleql(xml);
@@ -188,7 +188,7 @@ describe('ol.parser.gml_v2', function() {
var p = new ol.parser.ogc.GML_v2({srsName: 'foo', var p = new ol.parser.ogc.GML_v2({srsName: 'foo',
featureNS: 'http://foo'}); featureNS: 'http://foo'});
var obj = p.read(xml); var obj = p.read(xml);
var geom = p.createGeometry_({geometry: obj.geometry}); var geom = p.createGeometry({geometry: obj.geometry});
var node = p.featureNSWiters_['_geometry'].apply(p, var node = p.featureNSWiters_['_geometry'].apply(p,
[geom]).firstChild; [geom]).firstChild;
expect(goog.dom.xml.loadXml(p.serialize(node))).to.xmleql(xml); expect(goog.dom.xml.loadXml(p.serialize(node))).to.xmleql(xml);
@@ -231,7 +231,7 @@ describe('ol.parser.gml_v2', function() {
afterLoadXml(url, function(xml) { afterLoadXml(url, function(xml) {
var obj = parser.read(xml); var obj = parser.read(xml);
parser.srsName = 'foo'; parser.srsName = 'foo';
var geom = parser.createGeometry_({geometry: obj.geometry}); var geom = parser.createGeometry({geometry: obj.geometry});
var node = parser.featureNSWiters_['_geometry'].apply(parser, var node = parser.featureNSWiters_['_geometry'].apply(parser,
[geom]).firstChild; [geom]).firstChild;
expect(goog.dom.xml.loadXml(parser.serialize(node))).to.xmleql(xml); expect(goog.dom.xml.loadXml(parser.serialize(node))).to.xmleql(xml);

View File

@@ -17,7 +17,7 @@ describe('ol.parser.gml_v3', function() {
var url = 'spec/ol/parser/ogc/xml/gml_v3/linearring.xml'; var url = 'spec/ol/parser/ogc/xml/gml_v3/linearring.xml';
afterLoadXml(url, function(xml) { afterLoadXml(url, function(xml) {
var obj = parser.read(xml); var obj = parser.read(xml);
var geom = parser.createGeometry_({geometry: obj.geometry}); var geom = parser.createGeometry({geometry: obj.geometry});
parser.srsName = 'foo'; parser.srsName = 'foo';
var node = parser.featureNSWiters_['_geometry'].apply(parser, var node = parser.featureNSWiters_['_geometry'].apply(parser,
[geom]).firstChild; [geom]).firstChild;
@@ -33,7 +33,7 @@ describe('ol.parser.gml_v3', function() {
var url = 'spec/ol/parser/ogc/xml/gml_v3/linestring.xml'; var url = 'spec/ol/parser/ogc/xml/gml_v3/linestring.xml';
afterLoadXml(url, function(xml) { afterLoadXml(url, function(xml) {
var obj = parser.read(xml); var obj = parser.read(xml);
var geom = parser.createGeometry_({geometry: obj.geometry}); var geom = parser.createGeometry({geometry: obj.geometry});
parser.srsName = 'foo'; parser.srsName = 'foo';
var node = parser.featureNSWiters_['_geometry'].apply(parser, var node = parser.featureNSWiters_['_geometry'].apply(parser,
[geom]).firstChild; [geom]).firstChild;
@@ -59,7 +59,7 @@ describe('ol.parser.gml_v3', function() {
afterLoadXml(url, function(xml) { afterLoadXml(url, function(xml) {
var p = new ol.parser.ogc.GML_v3({curve: true, srsName: 'foo'}); var p = new ol.parser.ogc.GML_v3({curve: true, srsName: 'foo'});
var obj = p.read(xml); var obj = p.read(xml);
var geom = p.createGeometry_({geometry: obj.geometry}); var geom = p.createGeometry({geometry: obj.geometry});
var node = p.featureNSWiters_['_geometry'].apply(p, var node = p.featureNSWiters_['_geometry'].apply(p,
[geom]).firstChild; [geom]).firstChild;
expect(goog.dom.xml.loadXml(p.serialize(node))).to.xmleql(xml); expect(goog.dom.xml.loadXml(p.serialize(node))).to.xmleql(xml);
@@ -84,7 +84,7 @@ describe('ol.parser.gml_v3', function() {
afterLoadXml(url, function(xml) { afterLoadXml(url, function(xml) {
var p = new ol.parser.ogc.GML_v3({multiCurve: false, srsName: 'foo'}); var p = new ol.parser.ogc.GML_v3({multiCurve: false, srsName: 'foo'});
var obj = p.read(xml); var obj = p.read(xml);
var geom = p.createGeometry_({geometry: obj.geometry}); var geom = p.createGeometry({geometry: obj.geometry});
var node = p.featureNSWiters_['_geometry'].apply(p, var node = p.featureNSWiters_['_geometry'].apply(p,
[geom]).firstChild; [geom]).firstChild;
expect(goog.dom.xml.loadXml(p.serialize(node))).to.xmleql(xml); expect(goog.dom.xml.loadXml(p.serialize(node))).to.xmleql(xml);
@@ -99,7 +99,7 @@ describe('ol.parser.gml_v3', function() {
afterLoadXml(url, function(xml) { afterLoadXml(url, function(xml) {
var obj = parser.read(xml); var obj = parser.read(xml);
parser.srsName = 'foo'; parser.srsName = 'foo';
var geom = parser.createGeometry_({geometry: obj.geometry}); var geom = parser.createGeometry({geometry: obj.geometry});
var node = parser.featureNSWiters_['_geometry'].apply(parser, var node = parser.featureNSWiters_['_geometry'].apply(parser,
[geom]).firstChild; [geom]).firstChild;
expect(goog.dom.xml.loadXml(parser.serialize(node))).to.xmleql(xml); expect(goog.dom.xml.loadXml(parser.serialize(node))).to.xmleql(xml);
@@ -116,7 +116,7 @@ describe('ol.parser.gml_v3', function() {
afterLoadXml(url, function(xml) { afterLoadXml(url, function(xml) {
var p = new ol.parser.ogc.GML_v3({curve: true, srsName: 'foo'}); var p = new ol.parser.ogc.GML_v3({curve: true, srsName: 'foo'});
var obj = p.read(xml); var obj = p.read(xml);
var geom = p.createGeometry_({geometry: obj.geometry}); var geom = p.createGeometry({geometry: obj.geometry});
var node = p.featureNSWiters_['_geometry'].apply(p, var node = p.featureNSWiters_['_geometry'].apply(p,
[geom]).firstChild; [geom]).firstChild;
expect(goog.dom.xml.loadXml(p.serialize(node))).to.xmleql(xml); expect(goog.dom.xml.loadXml(p.serialize(node))).to.xmleql(xml);
@@ -143,7 +143,7 @@ describe('ol.parser.gml_v3', function() {
afterLoadXml(url, function(xml) { afterLoadXml(url, function(xml) {
var obj = parser.read(xml); var obj = parser.read(xml);
parser.srsName = 'foo'; parser.srsName = 'foo';
var geom = parser.createGeometry_({geometry: obj.geometry}); var geom = parser.createGeometry({geometry: obj.geometry});
var node = parser.featureNSWiters_['_geometry'].apply(parser, var node = parser.featureNSWiters_['_geometry'].apply(parser,
[geom]).firstChild; [geom]).firstChild;
expect(goog.dom.xml.loadXml(parser.serialize(node))).to.xmleql(xml); expect(goog.dom.xml.loadXml(parser.serialize(node))).to.xmleql(xml);
@@ -170,7 +170,7 @@ describe('ol.parser.gml_v3', function() {
afterLoadXml(url, function(xml) { afterLoadXml(url, function(xml) {
var p = new ol.parser.ogc.GML_v3({multiSurface: false, srsName: 'foo'}); var p = new ol.parser.ogc.GML_v3({multiSurface: false, srsName: 'foo'});
var obj = p.read(xml); var obj = p.read(xml);
var geom = p.createGeometry_({geometry: obj.geometry}); var geom = p.createGeometry({geometry: obj.geometry});
var node = p.featureNSWiters_['_geometry'].apply(p, var node = p.featureNSWiters_['_geometry'].apply(p,
[geom]).firstChild; [geom]).firstChild;
expect(goog.dom.xml.loadXml(p.serialize(node))).to.xmleql(xml); expect(goog.dom.xml.loadXml(p.serialize(node))).to.xmleql(xml);
@@ -195,7 +195,7 @@ describe('ol.parser.gml_v3', function() {
afterLoadXml(url, function(xml) { afterLoadXml(url, function(xml) {
var obj = parser.read(xml); var obj = parser.read(xml);
parser.srsName = 'foo'; parser.srsName = 'foo';
var geom = parser.createGeometry_({geometry: obj.geometry}); var geom = parser.createGeometry({geometry: obj.geometry});
var node = parser.featureNSWiters_['_geometry'].apply(parser, var node = parser.featureNSWiters_['_geometry'].apply(parser,
[geom]).firstChild; [geom]).firstChild;
expect(goog.dom.xml.loadXml(parser.serialize(node))).to.xmleql(xml); expect(goog.dom.xml.loadXml(parser.serialize(node))).to.xmleql(xml);
@@ -211,7 +211,7 @@ describe('ol.parser.gml_v3', function() {
afterLoadXml(url, function(xml) { afterLoadXml(url, function(xml) {
var p = new ol.parser.ogc.GML_v3({surface: true, srsName: 'foo'}); var p = new ol.parser.ogc.GML_v3({surface: true, srsName: 'foo'});
var obj = p.read(xml); var obj = p.read(xml);
var geom = p.createGeometry_({geometry: obj.geometry}); var geom = p.createGeometry({geometry: obj.geometry});
var node = p.featureNSWiters_['_geometry'].apply(p, var node = p.featureNSWiters_['_geometry'].apply(p,
[geom]).firstChild; [geom]).firstChild;
expect(goog.dom.xml.loadXml(p.serialize(node))).to.xmleql(xml); expect(goog.dom.xml.loadXml(p.serialize(node))).to.xmleql(xml);
@@ -225,7 +225,7 @@ describe('ol.parser.gml_v3', function() {
var url = 'spec/ol/parser/ogc/xml/gml_v3/point.xml'; var url = 'spec/ol/parser/ogc/xml/gml_v3/point.xml';
afterLoadXml(url, function(xml) { afterLoadXml(url, function(xml) {
var obj = parser.read(xml); var obj = parser.read(xml);
var geom = parser.createGeometry_({geometry: obj.geometry}); var geom = parser.createGeometry({geometry: obj.geometry});
parser.srsName = 'foo'; parser.srsName = 'foo';
var node = parser.featureNSWiters_['_geometry'].apply(parser, var node = parser.featureNSWiters_['_geometry'].apply(parser,
[geom]).firstChild; [geom]).firstChild;
@@ -240,7 +240,7 @@ describe('ol.parser.gml_v3', function() {
var url = 'spec/ol/parser/ogc/xml/gml_v3/polygon.xml'; var url = 'spec/ol/parser/ogc/xml/gml_v3/polygon.xml';
afterLoadXml(url, function(xml) { afterLoadXml(url, function(xml) {
var obj = parser.read(xml); var obj = parser.read(xml);
var geom = parser.createGeometry_({geometry: obj.geometry}); var geom = parser.createGeometry({geometry: obj.geometry});
parser.srsName = 'foo'; parser.srsName = 'foo';
var node = parser.featureNSWiters_['_geometry'].apply(parser, var node = parser.featureNSWiters_['_geometry'].apply(parser,
[geom]).firstChild; [geom]).firstChild;
@@ -263,7 +263,7 @@ describe('ol.parser.gml_v3', function() {
afterLoadXml(url, function(xml) { afterLoadXml(url, function(xml) {
var p = new ol.parser.ogc.GML_v3({surface: true, srsName: 'foo'}); var p = new ol.parser.ogc.GML_v3({surface: true, srsName: 'foo'});
var obj = p.read(xml); var obj = p.read(xml);
var geom = p.createGeometry_({geometry: obj.geometry}); var geom = p.createGeometry({geometry: obj.geometry});
var node = p.featureNSWiters_['_geometry'].apply(p, var node = p.featureNSWiters_['_geometry'].apply(p,
[geom]).firstChild; [geom]).firstChild;
expect(goog.dom.xml.loadXml(p.serialize(node))).to.xmleql(xml); expect(goog.dom.xml.loadXml(p.serialize(node))).to.xmleql(xml);

View File

@@ -0,0 +1,23 @@
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
<ogc:Or>
<ogc:PropertyIsBetween>
<ogc:PropertyName>number</ogc:PropertyName>
<ogc:LowerBoundary>
<ogc:Literal>1064866676</ogc:Literal>
</ogc:LowerBoundary>
<ogc:UpperBoundary>
<ogc:Literal>1065512599</ogc:Literal>
</ogc:UpperBoundary>
</ogc:PropertyIsBetween>
<ogc:PropertyIsLike wildCard="*" singleChar="." escape="!">
<ogc:PropertyName>cat</ogc:PropertyName>
<ogc:Literal>*dog.food!*good</ogc:Literal>
</ogc:PropertyIsLike>
<ogc:Not>
<ogc:PropertyIsLessThanOrEqualTo>
<ogc:PropertyName>FOO</ogc:PropertyName>
<ogc:Literal>5000</ogc:Literal>
</ogc:PropertyIsLessThanOrEqualTo>
</ogc:Not>
</ogc:Or>
</ogc:Filter>

View File

@@ -0,0 +1,8 @@
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/ogc http://schemas.opengis.net/filter/1.0.0/filter.xsd">
<ogc:BBOX>
<ogc:PropertyName>the_geom</ogc:PropertyName>
<gml:Box xmlns:gml="http://www.opengis.net/gml" srsName="EPSG:4326">
<gml:coordinates decimal="." cs="," ts=" ">-180,-90 180,90</gml:coordinates>
</gml:Box>
</ogc:BBOX>
</ogc:Filter>

View File

@@ -0,0 +1,7 @@
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/ogc http://schemas.opengis.net/filter/1.0.0/filter.xsd">
<ogc:BBOX>
<gml:Box xmlns:gml="http://www.opengis.net/gml" srsName="EPSG:4326">
<gml:coordinates decimal="." cs="," ts=" ">-180,-90 180,90</gml:coordinates>
</gml:Box>
</ogc:BBOX>
</ogc:Filter>

View File

@@ -0,0 +1,11 @@
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/ogc http://schemas.opengis.net/filter/1.0.0/filter.xsd">
<ogc:PropertyIsBetween>
<ogc:PropertyName>number</ogc:PropertyName>
<ogc:LowerBoundary>
<ogc:Literal>0</ogc:Literal>
</ogc:LowerBoundary>
<ogc:UpperBoundary>
<ogc:Literal>100</ogc:Literal>
</ogc:UpperBoundary>
</ogc:PropertyIsBetween>
</ogc:Filter>

View File

@@ -0,0 +1,7 @@
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
<ogc:PropertyIsBetween>
<ogc:PropertyName>number</ogc:PropertyName>
<ogc:LowerBoundary>0</ogc:LowerBoundary>
<ogc:UpperBoundary>100</ogc:UpperBoundary>
</ogc:PropertyIsBetween>
</ogc:Filter>

View File

@@ -0,0 +1,11 @@
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/ogc http://schemas.opengis.net/filter/1.0.0/filter.xsd">
<ogc:PropertyIsBetween>
<ogc:PropertyName>when</ogc:PropertyName>
<ogc:LowerBoundary>
<ogc:Literal>2010-11-27T18:19:15.123Z</ogc:Literal>
</ogc:LowerBoundary>
<ogc:UpperBoundary>
<ogc:Literal>2011-12-27T18:19:15.123Z</ogc:Literal>
</ogc:UpperBoundary>
</ogc:PropertyIsBetween>
</ogc:Filter>

View File

@@ -0,0 +1,12 @@
<Filter xmlns="http://www.opengis.net/ogc" xsi:schemaLocation="http://www.opengis.net/ogc http://schemas.opengis.net/filter/1.0.0/filter.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Contains>
<PropertyName>Geometry</PropertyName>
<gml:Polygon xmlns:gml="http://www.opengis.net/gml">
<gml:outerBoundaryIs>
<gml:LinearRing>
<gml:coordinates decimal="." cs="," ts=" ">2488789,289552 2588789,289552 2588789,389552 2488789,389552 2488789,289552</gml:coordinates>
</gml:LinearRing>
</gml:outerBoundaryIs>
</gml:Polygon>
</Contains>
</Filter>

View File

@@ -0,0 +1,11 @@
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
<ogc:PropertyIsBetween>
<ogc:PropertyName>when</ogc:PropertyName>
<ogc:LowerBoundary>
<ogc:Literal>2010-11-27</ogc:Literal>
</ogc:LowerBoundary>
<ogc:UpperBoundary>
<ogc:Literal>2011-12-27</ogc:Literal>
</ogc:UpperBoundary>
</ogc:PropertyIsBetween>
</ogc:Filter>

View File

@@ -0,0 +1,9 @@
<Filter xmlns="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/ogc http://schemas.opengis.net/filter/1.0.0/filter.xsd">
<DWithin>
<PropertyName>Geometry</PropertyName>
<gml:Point xmlns:gml="http://www.opengis.net/gml">
<gml:coordinates decimal="." cs="," ts=" ">2488789,289552</gml:coordinates>
</gml:Point>
<Distance units="m">1000</Distance>
</DWithin>
</Filter>

View File

@@ -0,0 +1,12 @@
<Filter xmlns="http://www.opengis.net/ogc" xsi:schemaLocation="http://www.opengis.net/ogc http://schemas.opengis.net/filter/1.0.0/filter.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Intersects>
<PropertyName>Geometry</PropertyName>
<gml:Polygon xmlns:gml="http://www.opengis.net/gml">
<gml:outerBoundaryIs>
<gml:LinearRing>
<gml:coordinates decimal="." cs="," ts=" ">2488789,289552 2588789,289552 2588789,389552 2488789,389552 2488789,289552</gml:coordinates>
</gml:LinearRing>
</gml:outerBoundaryIs>
</gml:Polygon>
</Intersects>
</Filter>

View File

@@ -0,0 +1,10 @@
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/ogc http://schemas.opengis.net/filter/1.0.0/filter.xsd">
<ogc:Or>
<ogc:PropertyIsLike wildCard="*" singleChar="." escape="!">
<ogc:PropertyName>person</ogc:PropertyName>
<ogc:Literal>me</ogc:Literal>
</ogc:PropertyIsLike>
<ogc:FeatureId fid="foo.1"/>
<ogc:FeatureId fid="foo.2"/>
</ogc:Or>
</ogc:Filter>

View File

@@ -0,0 +1,10 @@
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/ogc http://schemas.opengis.net/filter/1.0.0/filter.xsd">
<ogc:And>
<ogc:PropertyIsLike wildCard="*" singleChar="." escape="!">
<ogc:PropertyName>person</ogc:PropertyName>
<ogc:Literal>me</ogc:Literal>
</ogc:PropertyIsLike>
<ogc:FeatureId fid="foo.1"/>
<ogc:FeatureId fid="foo.2"/>
</ogc:And>
</ogc:Filter>

View File

@@ -0,0 +1,5 @@
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/ogc http://schemas.opengis.net/filter/1.0.0/filter.xsd">
<ogc:Not>
<ogc:FeatureId fid="foo.2"/>
</ogc:Not>
</ogc:Filter>

View File

@@ -0,0 +1,5 @@
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/ogc http://schemas.opengis.net/filter/1.0.0/filter.xsd">
<ogc:PropertyIsNull>
<ogc:PropertyName>prop</ogc:PropertyName>
</ogc:PropertyIsNull>
</ogc:Filter>

View File

@@ -0,0 +1,12 @@
<Filter xmlns="http://www.opengis.net/ogc" xsi:schemaLocation="http://www.opengis.net/ogc http://schemas.opengis.net/filter/1.0.0/filter.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Within>
<PropertyName>Geometry</PropertyName>
<gml:Polygon xmlns:gml="http://www.opengis.net/gml">
<gml:outerBoundaryIs>
<gml:LinearRing>
<gml:coordinates decimal="." cs="," ts=" ">2488789,289552 2588789,289552 2588789,389552 2488789,389552 2488789,289552</gml:coordinates>
</gml:LinearRing>
</gml:outerBoundaryIs>
</gml:Polygon>
</Within>
</Filter>

View File

@@ -0,0 +1,9 @@
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/ogc http://schemas.opengis.net/filter/1.1.0/filter.xsd">
<ogc:BBOX>
<ogc:PropertyName>the_geom</ogc:PropertyName>
<gml:Envelope xmlns:gml="http://www.opengis.net/gml" srsName="EPSG:4326">
<gml:lowerCorner>-180 -90</gml:lowerCorner>
<gml:upperCorner>180 90</gml:upperCorner>
</gml:Envelope>
</ogc:BBOX>
</ogc:Filter>

View File

@@ -0,0 +1,8 @@
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/ogc http://schemas.opengis.net/filter/1.1.0/filter.xsd">
<ogc:BBOX>
<gml:Envelope xmlns:gml="http://www.opengis.net/gml" srsName="EPSG:4326">
<gml:lowerCorner>-180 -90</gml:lowerCorner>
<gml:upperCorner>180 90</gml:upperCorner>
</gml:Envelope>
</ogc:BBOX>
</ogc:Filter>

View File

@@ -0,0 +1,11 @@
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/ogc http://schemas.opengis.net/filter/1.1.0/filter.xsd">
<ogc:And>
<ogc:PropertyIsNotEqualTo matchCase="false">
<ogc:PropertyName>FOO</ogc:PropertyName>
<ogc:Function name="customFunction">
<ogc:Literal>param1</ogc:Literal>
<ogc:Literal>param2</ogc:Literal>
</ogc:Function>
</ogc:PropertyIsNotEqualTo>
</ogc:And>
</ogc:Filter>

View File

@@ -0,0 +1,10 @@
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/ogc http://schemas.opengis.net/filter/1.1.0/filter.xsd">
<ogc:Intersects>
<ogc:PropertyName>the_geom</ogc:PropertyName>
<ogc:Function name="querySingle">
<ogc:Literal>sf:restricted</ogc:Literal>
<ogc:Literal>the_geom</ogc:Literal>
<ogc:Literal>cat=3</ogc:Literal>
</ogc:Function>
</ogc:Intersects>
</ogc:Filter>

View File

@@ -0,0 +1,9 @@
<Filter xmlns="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/ogc http://schemas.opengis.net/filter/1.1.0/filter.xsd">
<Intersects>
<PropertyName>Geometry</PropertyName>
<gml:Envelope xmlns:gml="http://www.opengis.net/gml" srsName="EPSG:4326">
<gml:lowerCorner>-180 -90</gml:lowerCorner>
<gml:upperCorner>180 90</gml:upperCorner>
</gml:Envelope>
</Intersects>
</Filter>

View File

@@ -0,0 +1,6 @@
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/ogc http://schemas.opengis.net/filter/1.1.0/filter.xsd">
<ogc:PropertyIsLike wildCard="*" singleChar="." escapeChar="!" matchCase="false">
<ogc:PropertyName>person</ogc:PropertyName>
<ogc:Literal>*me*</ogc:Literal>
</ogc:PropertyIsLike>
</ogc:Filter>

View File

@@ -0,0 +1,13 @@
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/ogc http://schemas.opengis.net/filter/1.1.0/filter.xsd">
<ogc:DWithin>
<ogc:PropertyName>the_geom</ogc:PropertyName>
<ogc:Function name="collectGeometries">
<ogc:Function name="queryCollection">
<ogc:Literal>sf:roads</ogc:Literal>
<ogc:Literal>the_geom</ogc:Literal>
<ogc:Literal>INCLUDE</ogc:Literal>
</ogc:Function>
</ogc:Function>
<ogc:Distance units="meters">200</ogc:Distance>
</ogc:DWithin>
</ogc:Filter>

View File

@@ -0,0 +1,10 @@
<ogc:SortBy xmlns:ogc="http://www.opengis.net/ogc">
<ogc:SortProperty>
<ogc:PropertyName>Title</ogc:PropertyName>
<ogc:SortOrder>ASC</ogc:SortOrder>
</ogc:SortProperty>
<ogc:SortProperty>
<ogc:PropertyName>Relevance</ogc:PropertyName>
<ogc:SortOrder>DESC</ogc:SortOrder>
</ogc:SortProperty>
</ogc:SortBy>

View File

@@ -0,0 +1,31 @@
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/ogc http://schemas.opengis.net/filter/1.1.0/filter.xsd">
<ogc:Or>
<ogc:PropertyIsBetween>
<ogc:PropertyName>number</ogc:PropertyName>
<ogc:LowerBoundary>
<ogc:Literal>1064866676</ogc:Literal>
</ogc:LowerBoundary>
<ogc:UpperBoundary>
<ogc:Literal>1065512599</ogc:Literal>
</ogc:UpperBoundary>
</ogc:PropertyIsBetween>
<ogc:PropertyIsLike wildCard="*" singleChar="." escapeChar="!">
<ogc:PropertyName>cat</ogc:PropertyName>
<ogc:Literal>*dog.food!*good</ogc:Literal>
</ogc:PropertyIsLike>
<ogc:Not>
<ogc:PropertyIsLessThanOrEqualTo>
<ogc:PropertyName>FOO</ogc:PropertyName>
<ogc:Literal>5000</ogc:Literal>
</ogc:PropertyIsLessThanOrEqualTo>
</ogc:Not>
<ogc:PropertyIsEqualTo>
<ogc:PropertyName>cat</ogc:PropertyName>
<ogc:Literal>dog</ogc:Literal>
</ogc:PropertyIsEqualTo>
<ogc:PropertyIsEqualTo matchCase="false">
<ogc:PropertyName>cat</ogc:PropertyName>
<ogc:Literal>dog</ogc:Literal>
</ogc:PropertyIsEqualTo>
</ogc:Or>
</ogc:Filter>