Hi, That was the one documentation I was missing. I do want to make a function that extracts this information, rather than a xpath accessor. It would've been nice if that function wasn't too verbose. I will look more into your examples and see how it can be done.
I'm pretty sure there is some bugs there, so I will make some tickets for those. Maybe I will do something about the documentation as well. Thanks for your time, Jody. Regards, Roar Brænden > 1. sep. 2021 kl. 00:21 skrev Jody Garnett <jody.garn...@gmail.com>: > > 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 > > <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 > <mailto: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 >> <mailto: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