GeoTools WFS-ng 插件 - WFS GetFeature 请求在解析响应时失败

问题描述 投票:0回答:1

我正在尝试从此在线 WFS 服务加载数据:

https://inspire.skgeodesy.sk/eskn/rest/services/INSPIREWFS/kn_wfs_inspire/GeoDataServer/exts/InspireFeatureDownload/service?VERSION=2.0.0&SERVICE=WFS&REQUEST=GetCapabilities

我正在使用 wfs-ng geotools 插件,但在尝试使用 GetFeature 请求类型查询数据时遇到问题。

这是代码:

    public List<KatastralneUzemieAdminHraniceEntity> administrativneHraniceKatastralneUzemie() throws IOException {
        WFSDataStore dataStore = createWFSDatastoreKatastralneUzemie();
        //ContentFeatureSource featureSource = dataStore.getFeatureSource(esknEiaProperties.getKatastralneUzemieWFSNazovFeature());

        List<KatastralneUzemieAdminHraniceEntity> katastralneUzemieAdminHraniceEntityList = new ArrayList<>();

        // Define query parameters
        String typeName = "cp:CadastralZoning"; // Feature type name
        Filter filter = Filter.INCLUDE; // Include all features
        String[] propertyNames = null; // Retrieve all properties
        Integer maxFeatures = 1; // Max features to return

        // Create query
        Query query = new Query(typeName, filter, propertyNames);
        query.setMaxFeatures(maxFeatures);

        // Execute query
        SimpleFeatureSource featureSource = dataStore.getFeatureSource(typeName);
        SimpleFeatureCollection features = featureSource.getFeatures(query);

        // Process returned features
        System.out.println("Returned Features:");
        try (SimpleFeatureIterator iterator = features.features()) {
            while (iterator.hasNext()) {
                SimpleFeature feature = iterator.next();
                System.out.println(feature.getID() + ": " + feature.getProperties());
            }
        }

        // Close the data store
        dataStore.dispose();
        return katastralneUzemieAdminHraniceEntityList;
    }
    private WFSDataStore createWFSDatastoreKatastralneUzemie() throws IOException {
        String wfsUrl = "https://inspire.skgeodesy.sk/eskn/rest/services/INSPIREWFS/kn_wfs_inspire/GeoDataServer/exts/InspireFeatureDownload/service?";

        // Create parameters for the WFS DataStore
        Map<String, Object> params = new HashMap<>();
        params.put(WFSDataStoreFactory.URL.key, wfsUrl);
        params.put(WFSDataStoreFactory.PROTOCOL.key, Boolean.FALSE);


        WFSDataStore dataStore = createDatastorePreKatastralneUzemiaInternal(params);
        return dataStore;
    }

这类似于从插件调用 wfsDataStoreFactory.createDataStore(params)。我必须创建自定义 WFSClient,否则我无法接收任何数据。

    private WFSDataStore createDatastorePreKatastralneUzemiaInternal(final Map<String, ?> params) throws IOException {
        final WFSConfig config = WFSConfig.fromParams(params);

        {
            String user = config.getUser();
            String password = config.getPassword();
            if (((user == null) && (password != null))
                    || ((config.getPassword() == null) && (config.getUser() != null))) {
                throw new IOException(
                        "Cannot define only one of USERNAME or PASSWORD, must define both or neither");
            }
        }

        final URL capabilitiesURL = org.geotools.data.wfs.impl.WFSDataAccessFactory.URL.lookUp(params);

        final HTTPClient http = wfsDataStoreFactory.getHttpClient(params);
        http.setTryGzip(config.isTryGZIP());
        http.setUser(config.getUser());
        http.setPassword(config.getPassword());
        int timeoutMillis = config.getTimeoutMillis();
        http.setConnectTimeout(timeoutMillis / 1000);
        http.setReadTimeout(timeoutMillis / 1000);

        // WFSClient performs version negotiation and selects the correct strategy
        WFSClient wfsClient;
        try {
            wfsClient = new WFSClientCustom(capabilitiesURL, http, config);
        } catch (ServiceException e) {
            throw new IOException(e);
        }

        WFSDataStore dataStore = new WFSDataStore(wfsClient);
        // factories
        dataStore.setFilterFactory(CommonFactoryFinder.getFilterFactory(null));
        dataStore.setGeometryFactory(
                new GeometryFactory(PackedCoordinateSequenceFactory.DOUBLE_FACTORY));
        dataStore.setFeatureTypeFactory(new FeatureTypeFactoryImpl());
        dataStore.setFeatureFactory(CommonFactoryFinder.getFeatureFactory(null));
        //dataStore.setDataStoreFactory(wfsDataStoreFactory);
        dataStore.setNamespaceURI(config.getNamespaceOverride());

        return dataStore;
    }
public class WFSClientCustom extends WFSClient {

    public WFSClientCustom(URL capabilitiesURL, HTTPClient httpClient, WFSConfig config) throws IOException, ServiceException {
        super(capabilitiesURL, httpClient, config);
        super.specification = new StrictWFS_2_0_Strategy() {
            @Override
            protected Map<String, String> buildGetFeatureParametersForGET(GetFeatureRequest query) {
                Map<String, String> kvp = super.buildGetFeatureParametersForGET(query);
                kvp.put("NAMESPACES", "xmlns(cp,http://inspire.ec.europa.eu/schemas/cp/4.0)");
                return kvp;
            }
        };
        ((WFSStrategy) specification).setCapabilities(super.capabilities);
    }
}

我必须使用自定义 WFSClient 创建自定义 WFSDataStore,因为如果 GetFeature 调用中的“NAMESPACES”参数值为“xmlns(cp,http://inspire.ec.europa.eu/schemas/cp/4.0),服务将不会响应” )”)”。

现在与服务器的通信工作正常,但我无法让内部解析器使用以下错误堆栈跟踪将响应中的数据解析到 SimpleFeatureIterator 中:

apr 18, 2024 9:19:00 AM org.geotools.xsd.impl.HTTPURIHandler getConnection
INFO: https://inspire.skgeodesy.sk/eskn/rest/directories/arcgisforinspire/schema/networkservices/inspire_fds/1.0/inspire_dls.xsd
2024-04-18 09:19:03,101 INFO  [main] [---] hsqldb.db.HSQLDB6BD103EBD8.ENGINE invoke0:-2 - dataFileCache open start
Returned Features:
apr 18, 2024 9:19:05 AM org.geotools.xsd.Schemas getImports
INFO: Schema import wasn't resolved: http://inspire.ec.europa.eu/schemas/ad/4.0 declared location: ad/4.0/Addresses.xsd
apr 18, 2024 9:19:05 AM org.geotools.xsd.Schemas getImports
INFO: Schema import wasn't resolved: http://inspire.ec.europa.eu/schemas/au/4.0 declared location: au/4.0/AdministrativeUnits.xsd
apr 18, 2024 9:19:05 AM org.geotools.xsd.Schemas getImports
INFO: Schema import wasn't resolved: http://inspire.ec.europa.eu/schemas/cp/4.0 declared location: cp/4.0/CadastralParcels.xsd
apr 18, 2024 9:19:05 AM org.geotools.xsd.Schemas getImports
INFO: Schema import wasn't resolved: http://inspire.ec.europa.eu/schemas/gn/4.0 declared location: gn/4.0/GeographicalNames.xsd
apr 18, 2024 9:19:05 AM org.geotools.xsd.Schemas getImports
INFO: Schema import wasn't resolved: http://inspire.ec.europa.eu/schemas/hy/4.0 declared location: hy/4.0/HydroBase.xsd
apr 18, 2024 9:19:05 AM org.geotools.xsd.Schemas getImports
INFO: Schema import wasn't resolved: http://inspire.ec.europa.eu/schemas/hy-p/4.0 declared location: hy-p/4.0/HydroPhysicalWaters.xsd
apr 18, 2024 9:19:05 AM org.geotools.xsd.Schemas getImports

java.lang.RuntimeException: Couldn't parse SimpleFeature of type SimpleFeatureTypeImpl http://inspire.ec.europa.eu/schemas/cp/4.0:CadastralZoning identified extends Feature(geometry:geometry,label:label,level:level,nationalCadastalZoningReference:nationalCadastalZoningReference,referencePoint:referencePoint,upperLevelUnit:upperLevelUnit) from xml.
identifier=https://inspire.skgeodesy.sk/eskn/rest/services/INSPIREWFS/kn_wfs_inspire/GeoDataServer/exts/InspireFeatureDownload/service?SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature&STOREDQUERY_ID=urn:ogc:def:query:OGC-WFS::GetFeatureById&id=cpZoningS.1
level={href=http://inspire.ec.europa.eu/codelist/CadastralZoningLevelValue/1stOrder, title=1stOrder}
levelName=katastrálne územie
label=Stanča
validFrom=2024-04-11T18:00:00
inspireId={versionId=null, namespace=SK.ESKN.CP, localId=873179}
referencePoint=POINT (48.564744882 21.657255808)
endLifespanVersion=null
beginLifespanVersion=null
nationalCadastalZoningReference=873179
upperLevelUnit=null
name={grammaticalGender=null, pronunciation=null, spelling={transliterationScheme=null, text=Stanča, script=null}, sourceOfName=null, grammaticalNumber=null, nameStatus=null, language=null, nativeness=null}
geometry=MULTIPOLYGON (((48.574338585 21.658480965, 48.574338191 21.658512458, 48.574338037  21.655316079, 48.574095809 21.656069217, 48.574328243 21.65784314, 48.574342838 21.658128299, 48.574338585 21.658480965)))
id=cpZoningS.1
originalMapScaleDenominator=null
estimatedAccuracy={null=-1.000000, uom=m}
validTo=null


    at org.geotools.data.store.ContentFeatureCollection.features(ContentFeatureCollection.java:176)
    at pam.eskn.wfs.WfsEsknClient.administrativneHraniceKatastralneUzemie(WfsEsknClient.java:234)
    at pam.AdminHraniceTest.testWfsKatastralneUzemie(AdminHraniceTest.java:72)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
Caused by: java.io.IOException: Couldn't parse SimpleFeature of type SimpleFeatureTypeImpl http://inspire.ec.europa.eu/schemas/cp/4.0:CadastralZoning identified extends Feature(geometry:geometry,label:label,level:level,nationalCadastalZoningReference:nationalCadastalZoningReference,referencePoint:referencePoint,upperLevelUnit:upperLevelUnit) from xml.
identifier=https://inspire.skgeodesy.sk/eskn/rest/services/INSPIREWFS/kn_wfs_inspire/GeoDataServer/exts/InspireFeatureDownload/service?SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature&STOREDQUERY_ID=urn:ogc:def:query:OGC-WFS::GetFeatureById&id=cpZoningS.1
level={href=http://inspire.ec.europa.eu/codelist/CadastralZoningLevelValue/1stOrder, title=1stOrder}
levelName=katastrálne územie
label=Stanča
validFrom=2024-04-11T18:00:00
inspireId={versionId=null, namespace=SK.ESKN.CP, localId=873179}
referencePoint=POINT (48.564744882 21.657255808)
endLifespanVersion=null
beginLifespanVersion=null
nationalCadastalZoningReference=873179
upperLevelUnit=null
name={grammaticalGender=null, pronunciation=null, spelling={transliterationScheme=null, text=Stanča, script=null}, sourceOfName=null, grammaticalNumber=null, nameStatus=null, language=null, nativeness=null}
geometry=MULTIPOLYGON (((48.574338585 21.658480965, 48.574338191 21.658512458, 48.574338037 21.660440916, 48.571672503 21.660582986, 48.571620629 21.660801476, 48.571430898 21.660870826, ...21.650799528, 48.573984887 21.650927851, 48.573980203 21.651022416, 48.57389808 21.65107354,21.655316079, 48.574095809 21.656069217, 48.574328243 21.65784314, 48.574342838 21.658128299, 48.574338585 21.658480965)))
id=cpZoningS.1
originalMapScaleDenominator=null
estimatedAccuracy={null=-1.000000, uom=m}
validTo=null

    at org.geotools.data.wfs.internal.parsers.PullParserFeatureReader.parse(PullParserFeatureReader.java:153)
    at org.geotools.data.wfs.internal.parsers.PullParserFeatureReader.parse(PullParserFeatureReader.java:50)
    at org.geotools.data.wfs.WFSFeatureReader.<init>(WFSFeatureReader.java:48)
    at org.geotools.data.wfs.WFSFeatureSource.getReaderInternal(WFSFeatureSource.java:298)
    at org.geotools.data.store.ContentFeatureSource.getReader(ContentFeatureSource.java:636)
    at org.geotools.data.store.ContentFeatureCollection.features(ContentFeatureCollection.java:174)
    ... 71 more

我尝试分析 geotools 库如何解析 xsd 架构,因为我怀疑该问题与外部架构和命名空间解析有关。

我可以将缺少的模式添加到 WFSDatastore 中吗?

java xsd geotools wfs
1个回答
0
投票

因此,此参数(或应该)仅在

GET
或 KVP 请求上需要(请参阅标准的第 6.3 节),因此明显的解决方法是切换到
POST
请求,这些请求是 XML 编码的并且应包含直接命名空间。但是,我只能通过
POST
请求获得超时。

虽然 GeoTools 的

StrictWFS_2_0_Strategy
确实设置了
NAMESPACES
值,但仅当

时才会这样做
!XMLConstants.DEFAULT_NS_PREFIX.equals(typeName.getPrefix())

可能值得打开一个增强请求来放宽该测试,并使用此 WFS 服务器为该代码添加一些单元测试。但请记住,它是任何不受支持的模块,因此不能保证任何人都会查看它。

© www.soinside.com 2019 - 2024. All rights reserved.