Details
-
Type:
Improvement
-
Status:
Closed
-
Priority:
Minor
-
Resolution: Fixed
-
Affects Version/s: 2.7-M4
-
Fix Version/s: None
-
Component/s: xml
-
Labels:None
-
Environment:all
Description
Consider the following situation documents:
doc1.xml:
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="schema.xsd"> <value>3.14159</value> </root>
doc2.xml:
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="schema.xsd"> <value></value> </root>
doc3.xml:
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="schema.xsd"> <value xsi:nil="true"></value> </root>
schema.xsd:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element name="value" type="xs:double" minOccurs="0" nillable="true"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Obviously, doc2.xml is invalid, as an empty string is not a valid double. doc1.xml and doc3.xml are valid.
In practice, I come across XML like doc2.xml in a gml:featureMember attribute element from an ArcGIS WFS service (except the element is not nillable according to DescribeFeatureType). When parsing the GML from a GetFeature request, the following exception occurs:
java.io.IOException: org.xml.sax.SAXException: empty String at org.geotools.xml.gml.FCBuffer.hasNext(FCBuffer.java:326) at org.geotools.data.wfs.v1_0_0.WFSFeatureReader.loadElement(WFSFeatureReader.java:189) at org.geotools.data.wfs.v1_0_0.WFSFeatureReader.hasNext(WFSFeatureReader.java:178) at org.geotools.data.wfs.v1_0_0.NonStrictWFSStrategy.createFeatureReaderGET(NonStrictWFSStrategy.java:134) at org.geotools.data.wfs.v1_0_0.NonStrictWFSStrategy.createFeatureReader(NonStrictWFSStrategy.java:101) at org.geotools.data.wfs.v1_0_0.StrictWFSStrategy.access$101(StrictWFSStrategy.java:60) at org.geotools.data.wfs.v1_0_0.StrictWFSStrategy$StrictFeatureReader.nextReader(StrictWFSStrategy.java:222) at org.geotools.data.wfs.v1_0_0.StrictWFSStrategy$StrictFeatureReader.init(StrictWFSStrategy.java:171) at org.geotools.data.wfs.v1_0_0.StrictWFSStrategy$StrictFeatureReader.<init>(StrictWFSStrategy.java:145) at org.geotools.data.wfs.v1_0_0.StrictWFSStrategy.createFeatureReader(StrictWFSStrategy.java:84) at org.geotools.data.wfs.v1_0_0.NonStrictWFSStrategy.getFeatureReader(NonStrictWFSStrategy.java:72) at org.geotools.data.wfs.v1_0_0.WFS_1_0_0_DataStore.getFeatureReader(WFS_1_0_0_DataStore.java:747) Caused by: org.xml.sax.SAXException: empty String at org.geotools.data.wfs.v1_0_0.WFSFeatureReader.run(WFSFeatureReader.java:140)
The root exception location is actually not immediately apparent but here it is:
java.lang.NumberFormatException: empty String
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:994)
at java.lang.Double.valueOf(Double.java:475)
at java.lang.Double.<init>(Double.java:567)
at org.geotools.xml.xsi.XSISimpleTypes$Double.getValue(XSISimpleTypes.java:1123)
at org.geotools.xml.handlers.SimpleElementHandler.endElement(SimpleElementHandler.java:123)
As fixing the WFS to produce valid XML is not feasible, I would like to propose a patch to GeoTools to treat this as a null value instead.
This could either be changing org.geotools.xml.handlers.SimpleElementHandler.endElement() to set "text" to null if text is an empty string and the type is numeric (maybe dates as well), or change the getValue() methods for each of the relevant inner classes (Integer, Double, Decimal, etc.) in org.geotools.xml.xsi.XSISimpleTypes from
if ((value.length == 1) && (value[0].getValue() != null)) {
return new java.lang.Double((java.lang.String) value[0]
.getValue());
}
to
if ((value.length == 1) && (value[0].getValue() != null) && (!"".equals(value[0])) {
return new java.lang.Double((java.lang.String) value[0]
.getValue());
}
or
if ((value.length == 1) && (value[0].getValue() != null)) {
try {
return new java.lang.Double((java.lang.String) value[0]
.getValue());
} catch(NumberFormatException nfe) {
return null;
}
}
Changing SimpleElementHandler would however affect all SimpleTypes, it would not be correct to change an empty string for a xs:string element to null of course.
I meant here "Changing SimpleElementHandler to convert a empty "text" to null for any and all types would not be correct..." therefore it would need to be type dependent (numeric, maybe dates). So the changes in XSISimpleTypes inner classes would make more sense.