[Geoserver-users] Adding a servlet filter for XSL transformation on WFS gml

Hi

I have to build a new filter for transforming with a XSL file the WFS gml
result of geoserver.
Could you give me some advice regarding where to put in the filterchain
(acegi, gzip, etc ...) and if you have any clue on how to implement it
considering how the WFS output is sent by geoserver (i'm a little lost with
Dispatchers, Spring and different outputStrategy)

Thanx in advance

Manu
--
View this message in context: http://www.nabble.com/Adding-a-servlet-filter-for-XSL-transformation-on-WFS-gml-tp19569283p19569283.html
Sent from the GeoServer - User mailing list archive at Nabble.com.

This is what I used for the GeoServer community schema version but the approach is equally applicable to any standard edition of GeoServer. In short, this approach intercepts the original GML response from GeoServer before it is returned to the client, transforms the GML into something else using an XSLT file and finally return the modified output to the client. Hope it helps.

/* Copyright (c) 2001 - 2007 TOPP - www.openplans.org. All rights reserved.
* This code is licensed under the GPL 2.0 license, availible at the root
* application directory.
*/
package org.geoserver.wfs.xml;

import net.opengis.wfs.BaseRequestType;
import net.opengis.wfs.FeatureCollectionType;
import net.opengis.wfs.GetFeatureType;
import org.eclipse.xsd.XSDSchema;
import org.geoserver.ows.util.RequestUtils;
import org.geoserver.ows.util.ResponseUtils;
import org.geoserver.platform.Operation;
import org.geoserver.platform.ServiceException;
import org.geoserver.wfs.GetFeature;
import org.geoserver.wfs.WFS;
import org.geoserver.wfs.WFSGetFeatureOutputFormat;
import org.geoserver.wfs.xml.v1_1_0.WFSConfiguration;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureType;
import org.geotools.xml.Encoder;
import org.opengis.feature.type.AttributeDescriptor;
import org.opengis.feature.type.Name;
import org.vfny.geoserver.global.Data;
import org.vfny.geoserver.global.FeatureTypeInfo;
import org.xml.sax.SAXException;
import java.io.*;
import java.util.*;

public class GML3OutputFormat extends WFSGetFeatureOutputFormat {
    WFS wfs;
    Data catalog;
    WFSConfiguration configuration;

    public GML3OutputFormat(WFS wfs, Data catalog, WFSConfiguration configuration) {
        super(new HashSet(Arrays.asList(new Object { "gml3", "text/xml; subtype=gml/3.1.1" })));

        this.wfs = wfs;
        this.catalog = catalog;
        this.configuration = configuration;
    }

    public String getMimeType(Object value, Operation operation) {
        return "text/xml; subtype=gml/3.1.1";
    }

    public String getCapabilitiesElementName() {
        return "GML3";
    }

    protected void write(FeatureCollectionType results, OutputStream output, Operation getFeature)
        throws ServiceException, IOException {
        List featureCollections = results.getFeature();

        //round up the info objects for each feature collection
        HashMap /*<String,Set>*/ ns2metas = new HashMap();

        for (Iterator fc = featureCollections.iterator(); fc.hasNext():wink: {
            GetFeature.GTHackFeatureCollection features;
            features = (GetFeature.GTHackFeatureCollection) fc.next();

            AttributeDescriptor descriptor = features.getISOFeatureType();

            //load the metadata for the feature type
            Name name = descriptor.getName();
            String namespaceURI = name.getNamespaceURI();
            String localPart = name.getLocalPart();
            FeatureTypeInfo meta = catalog.getFeatureTypeInfo(localPart, namespaceURI);

            //add it to the map
            Set metas = (Set) ns2metas.get(namespaceURI);

            if (metas == null) {
                metas = new HashSet();
                ns2metas.put(namespaceURI, metas);
            }

            metas.add(meta);
        }

        XSDSchema schema = configuration.schema();
        Encoder encoder = new Encoder(configuration, schema);

        //declare wfs schema location
        BaseRequestType gft = (BaseRequestType) getFeature.getParameters()[0];

        String proxifiedBaseUrl = RequestUtils.proxifiedBaseURL(gft.getBaseUrl(),
                wfs.getGeoServer().getProxyBaseUrl());
        encoder.setSchemaLocation(org.geoserver.wfs.xml.v1_1_0.WFS.NAMESPACE,
            ResponseUtils.appendPath(proxifiedBaseUrl, "schemas/wfs/1.1.0/wfs.xsd"));

        String featureType =""; //to record name of the feature type
        //declare application schema namespaces

        for (Iterator i = ns2metas.entrySet().iterator(); i.hasNext():wink: {
            Map.Entry entry = (Map.Entry) i.next();

            String namespaceURI = (String) entry.getKey();
            Set metas = (Set) entry.getValue();

            StringBuffer typeNames = new StringBuffer();

            for (Iterator m = metas.iterator(); m.hasNext():wink: {
                FeatureTypeInfo meta = (FeatureTypeInfo) m.next();
                typeNames.append(meta.getName());

                if (m.hasNext()) {
                    typeNames.append(",");
                }
            }

    featureType = typeNames.toString().substring(typeNames.toString().indexOf(":")+1);
            System.out.println("1 "+typeNames.toString()+" Hello");

            //set the schema location
            encoder.setSchemaLocation(namespaceURI,
                ResponseUtils.appendQueryString(proxifiedBaseUrl + "wfs",
                    "service=WFS&version=1.1.0&request=DescribeFeatureType&typeName="
                    + typeNames.toString()));
        }
        File gmlFile= null;
        FileOutputStream fos = null;
        DataOutputStream dos = null;
        FileInputStream fis = null;
        try {
       
             String root = wfs.getData().getDataDirectory().getAbsolutePath();
             
             //write gml to MyFile.xml
             
    //determine xslt location for featureType
             Properties xslConf = new Properties();
             fis = new FileInputStream(root+"/xsl_conf/xsl_conf.config");
             xslConf.load(fis);
             fis.close();
             String xslLocation ="";
             if (xslConf.containsKey(featureType)){
         gmlFile= new File(root+"/temp/MyFile"+System.currentTimeMillis()+".xml");
                 //System.out.println(gmlFile.getAbsolutePath());
                 fos = new FileOutputStream(gmlFile);
                 dos=new DataOutputStream(fos);
         encoder.encode(results, org.geoserver.wfs.xml.v1_1_0.WFS.FEATURECOLLECTION, dos);
                 xslLocation = root+"/"+xslConf.getProperty(featureType);
                  new XSLTTransform(gmlFile,
                    new File(xslLocation), output).doTransform();

      fos.close();
              dos.close();
              output.close();
              gmlFile.delete();
             }else{
             
      encoder.encode(results, org.geoserver.wfs.xml.v1_1_0.WFS.FEATURECOLLECTION, output);
     }
            //do housekeeping
            
        } catch (SAXException e) {
        fos.close();
                dos.close();
                output.close();
                gmlFile.delete();
            String msg = "Error occurred encoding features";
            throw (IOException) new IOException(msg).initCause(e);
        }catch (FileNotFoundException ex){
    System.out.println("File not found...");
    fos.close();
                dos.close();
                output.close();
                gmlFile.delete();
    throw new FileNotFoundException();
    }

    }
}

-----Original Message-----
From: geoserver-users-bounces@lists.sourceforge.net [mailto:geoserver-users-bounces@lists.sourceforge.net] On Behalf Of Emmanuel Séguin
Sent: 19 September 2008 10:42
To: geoserver-users@lists.sourceforge.net
Subject: [Geoserver-users] Adding a servlet filter for XSL transformation on WFS gml

Hi

I have to build a new filter for transforming with a XSL file the WFS gml
result of geoserver.
Could you give me some advice regarding where to put in the filterchain
(acegi, gzip, etc ...) and if you have any clue on how to implement it
considering how the WFS output is sent by geoserver (i'm a little lost with
Dispatchers, Spring and different outputStrategy)

Thanx in advance

Manu
--
View this message in context: http://www.nabble.com/Adding-a-servlet-filter-for-XSL-transformation-on-WFS-gml-tp19569283p19569283.html
Sent from the GeoServer - User mailing list archive at Nabble.com.

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Geoserver-users mailing list
Geoserver-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/geoserver-users

Shaon, ABS (Arif) ha scritto:

This is what I used for the GeoServer community schema version but
the approach is equally applicable to any standard edition of
GeoServer. In short, this approach intercepts the original GML
response from GeoServer before it is returned to the client,
transforms the GML into something else using an XSLT file and finally
return the modified output to the client. Hope it helps.

Ah ha, this is really interesting, I've been meaning to add an XSLT
output format since quite some time. So this one expects a property
file that maps feature types to an XSLT transform, stores the GML
on disk, and then applies it before returning the data.
Good good. Wondering if it makes any sense to have the xslt transform
location provided as a request parameter.

Interested in contributing this as part of a community extension?
Maybe even as part of the core GeoServer distribution...

Cheers
Andrea

--
Andrea Aime
OpenGeo - http://opengeo.org
Expert service straight from the developers.