Sorry I do not have more time for this, there are a couple spots which seem really odd to me in your example.
(Collection<Property>) nextFeature.getProperty("kommunenavn").getValue() I was trying to sort out why this was a collection - it does not match any of the examples in the javadocs here ( https://docs.geotools.org/latest/javadocs/org/opengis/feature/ComplexAttribute.html ). Do you have the feature model information (descriptors and types if you are building by hand, or the XSD if you are building from an XML Schema). I find I am making too many guesses without a guide :D It also looks like you are working very hard to query information out of your data structure; a property accessor should be able to help. PropertyName xpath = factory.property( "foo/bar" ); Property bar = xpath.evaluate( attribute ); It is known that GML is very verbose, with many of the examples repeating information. It took me a while to see the naming convention identifikasjon vs Identifikasjon. I do not know why there is not a single identifikasjon with multiplicity 1..N ? Is that a decision the application schema author made? -- Jody Garnett On Tue, 31 Aug 2021 at 13:46, Roar Brænden <roar.brenden...@gmail.com> wrote: > 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> > 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" >> 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> >> <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/ >> 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