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 <jody.garn...@gmail.com>: > > 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 <roar.brenden...@gmail.com > <mailto:roar.brenden...@gmail.com>> 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 GeoTools-Devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/geotools-devel