Hi,
Thanks for the response Jody.
In my original example there was only one kommunenavn, but here I've found one
with two kommunenavn's:
<app:kommunenavn>
<app:AdministrativEnhetNavn>
<app:navn>Hattfjelldal</app:navn>
<app:språk>nor</app:språk>
</app:AdministrativEnhetNavn>
<app:AdministrativEnhetNavn>
<app:navn>Aarborte</app:navn>
<app:språk>sma</app:språk>
</app:AdministrativEnhetNavn>
</app:kommunenavn>
The main goal of my query, is to extract the <app:navn>-element of the
<app:AdministrativEnhetNavn> where there is an <app:språk>nor</app:språk>.
I've prepared an example at Github
<https://github.com/roarbra/geotools/blob/d2aea334b6e26d252386db0b594dd1034ee33970/modules/unsupported/wfs-ng/src/test/java/org/geotools/data/wfs/KartverketKommuneReader.java>.
Here I've taken out the main parts, and written it as I would like it to be:
/* Ordinary feature iterator using getProperty to extract <app:kommunenummer>
and <app:kommunenavn>. */
/* The content of <app:kommunenavn> must go through findNorskNavn() */
try (FeatureIterator<Feature> features =
kommuneSource.getFeatures().features()) {
while (features.hasNext()) {
Feature nextFeature = features.next();
String kommunenr =
(String)nextFeature.getProperty("kommunenummer").getValue();
String kommunenavn =
findNorskNavn((Collection<Property>)nextFeature
.getProperty("kommunenavn")
.getValue());
System.out.printf("%s : %s\n", kommunenr, kommunenavn);
}
}
/* Loop through all <app:AdministrativEnhetNavn>, return navn with språk=nor. */
String findNorskNavn(Collection<Property> alleNavn) {
for (Property inner : alleNavn) {
if (matchNorskSprak(inner)) {
return extractNavn(inner);
}
}
return "Without norwegian name.";
}
/* Return true if <app:AdministrativEnhetNavn> contains a
<app:språk>nor</app:språk> */
boolean matchNorskSprak(Property prop) {
for (Property inner : (Collection<Property>)prop.getValue()) {
if ("språk".equals(inner.getName().getLocalPart())
&& "nor".equals(inner.getValue())) {
return true;
}
}
return false;
}
/* Return content of <app:navn> within the <app:AdministrativEnhetNavn> */
String extractNavn(Property prop) {
for (Property inner : (Collection<Property>)prop.getValue()) {
if ("navn".equals(inner.getName().getLocalPart())) {
return (String) inner.getValue();
}
}
throw new RuntimeException("There should've been a \"navn\"
element.");
}
Any feedback would be welcome.
Regards,
Roar Brænden
> 31. aug. 2021 kl. 17:35 skrev Jody Garnett <[email protected]>:
>
> The use of complex features is mostly confined to the app-schema module, and
> that is a good source of test cases and examples.
>
> I helped setup the feature model to enable the app-schema team but did not
> get a chance to work on it beyond that. The toString representations are
> just to aid with debugging, the important asspect is the relationship between
> the classes to ensure they form a complete descriptive type system.
>
> Some additional comments inline:
>
> On Tue, Aug 31, 2021 at 1:21 AM Roar Brænden <[email protected]
> <mailto:[email protected]>> wrote:
> I have a WFS source that I try to fetch features from. The response is quite
> complex, and I've been using org.geotools.data.wfs.impl.WFSDataAccessFactory
> within gt-wfs-ng.
>
> I have not tried gt-wfs-ng with complex features myself I am curious how this
> will go.
>
> I feel there is something wrong about how this xml are represented as a
> object graph of Property, but there are so many JUnit tests confirming this
> structure, so I'm not sure how to make it better. There is also a lack of
> documentation / examples on how the structure should be.
>
> The data structure forms a graph of properties; just the same way you could
> form a data structure using maps and key/value pairs; or layout a java object
> in memory. They properties do support some use of user data if you need to
> hang additional information on the data structuring during processing or
> parsing etc…
>
> The type system describes how the layout should be in order to be valid. It
> is also responsible for defining the meaning of the values with associated
> description and other “metadata” details. As a side effect the metadata can
> also describe default values (useful when setting up a new data), or
> additional filters (that can be used to validate that the data makes sense).
>
> The last aspect of the data model is the ability to query values out. In
> addition to traversing the data structures this was designed for access via
> xpath (to support WFS xpath property access).
>
> I key test of this as a dynamic type system is if the feature type system
> describes the data structure well enough that you can construct a xpath
> expression to retrieve the content you wish.
>
> Here is an example of what the xml looks like:
>
> <wfs:member>
> <app:Kommune
> xmlns:app="http://skjema.geonorge.no/SOSI/produktspesifikasjon/AdmEnheter/4.1
> <http://skjema.geonorge.no/SOSI/produktspesifikasjon/AdmEnheter/4.1>"
> gml:id="kommune_view.357">
> <app:identifikasjon>
> <app:Identifikasjon>
> <app:lokalId>173103</app:lokalId>
>
> <app:navnerom>https://data.geonorge.no/sosi/administrativeenheter/fylker_kommuner</app:navnerom>
>
> <https://data.geonorge.no/sosi/administrativeenheter/fylker_kommuner%3C/app:navnerom%3E>
> <app:versjonId>4.1</app:versjonId>
> </app:Identifikasjon>
> </app:identifikasjon>
> <app:oppdateringsdato>2020-02-07T00:00:00</app:oppdateringsdato>
> <app:datauttaksdato>2021-01-04T10:07:10</app:datauttaksdato>
> <app:område>
> <!--Inlined geometry 'kommune_view.357_APP_OMRÅDE'-->
> <gml:Polygon gml:id="kommune_view.357_APP_OMRÅDE"
> srsName="urn:ogc:def:crs:EPSG::4258">
> <gml:exterior>
> <gml:LinearRing>
> <gml:posList>58.426581 6.605405 .....</gml:posList>
> </gml:LinearRing>
> </gml:exterior>
> </gml:Polygon>
> </app:område>
> <app:kommunenummer>4207</app:kommunenummer>
> <app:kommunenavn>
> <app:AdministrativEnhetNavn>
> <app:navn>Flekkefjord</app:navn>
> <app:språk>nor</app:språk>
> </app:AdministrativEnhetNavn>
> </app:kommunenavn>
> <app:samiskForvaltningsområde>false</app:samiskForvaltningsområde>
> </app:Kommune>
> </wfs:member>
>
>
> The <wfs:member><app:Kommune> is the root for a singe Feature. When calling
> getProperties you will get all the child elements of Kommune represented as a
> subclass of Property. That contains a name, value and binding. This works
> great for ordinary values as string, dates, boolean and geometry. The problem
> is when there's a child element, like for instance <app:kommunenavn>.
>
>
> This is represented as a ComplexAttribute and has a Collection as a value.
> The Collection is actually a Collection of Property's.
>
> I am confused here, do you mean that more than one kommunenavn is allowed?
> Like min occurs 0, max occurs N? If so you should get repeated individual
> properties rather than a single one with a collection value.
>
> Underneath I've tried to represent this. Ordinary Attribute's are written as:
> "name [type] : value", while ComplexAttribute's are written "name {" with new
> indentation for their nested properties:
>
> samiskForvaltningsområde [java.lang.Boolean]: false
> IdentifikasjonPropertyType {
> Identifikasjon {
> IdentifikasjonType {
> lokalId [java.lang.String]: 173103
> navnerom [java.lang.String]: https://data.geonorge.no/sosi/
> <https://data.geonorge.no/sosi/>
> versjonId [java.lang.String]: 4.1
> }
> }
> }
> kommunenummer [java.lang.String]: 4207
> AdministrativEnhetNavnPropertyType {
> AdministrativEnhetNavn {
> AdministrativEnhetNavnType {
> navn [java.lang.String]: Flekkefjord
> språk [java.lang.String]: nor
> }
> }
> }
> oppdateringsdato [java.sql.Timestamp]: 2020-02-07 01:00:00.0
> område [org.locationtech.jts.geom.Polygon]: POLYGON ((58.426581 6.605405,
> datauttaksdato [java.sql.Timestamp]: 2021-01-04 11:07:10.0
>
> If you have suggestions for the toStirng representations we welcome pull
> requests; they are mostly used to aid in debugging. With GML and JSON used
> between systems.
>
> I would like "IdentifikasjonPropertyType" to have the name "identifikasjon",
> and the property IdentifikasjonType is superfluous.
>
> I do not understand, the property is the only real thing (ie data structure).
> The property type describes how it operates.
>
> Do anyone have an idea why it's done like it is today, or do anyone have an
> opinion about my changes? It would be nice to hear about them.
>
> Thanks for this discussion I hope we can sort out how to accomplish what you
> wish.
>
> Jody
> --
> --
> Jody Garnett
_______________________________________________
GeoTools-Devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/geotools-devel