Apache Cocoon 2.2: Return paramater from action and use it in HTML page to fill table

StackOverflow https://stackoverflow.com/questions/21550156

  •  06-10-2022
  •  | 
  •  

Вопрос

What I want to do?

I'm working on a Apache Cocoon Project and want to find solution to return paramaters in HTML pages.

I need to get the parameter, which has ArrayList type, and use it in HTML page in order to fill a table. How can I do this? Is it correct to set a request parameter? If yes, then how to use it inside HTML code? If no, then how to return the parameter correctly?

ActionClass.java

public class ActionClass implements Action, ThreadSafe{


     public Map act(Redirector rdrctr, org.apache.cocoon.environment.SourceResolver sr, Map map, String string, Parameters params) throws Exception {


               // READ REQUEST
               Request request = ObjectModelHelper.getRequest(map);


               // DO SOMETHING XQUERY VIA BASEX, SPARQL RDFSTORE WHATEVER
               ArrayList<ResultBean> results = xquery();


               Map sitemapParams = new HashMap();

               // SET REQUEST PARAMETER
               request.setAttribute("results",results);

               return sitemapParams;
    }

}

ResultBean.java

package com.kiddo.grlegislation;

public class ResultBean {

    private String id;
    private String title;
    private String type;

    public void setId(String i){
        this.id = i;
    };

     public void setTitle(String t){
        this.title = t;
    };

    public String getId(){
        return this.id;
    };

    public String getTitle(){
        return this.title;
    };



}
Это было полезно?

Решение

First of all, are you sure that you need an Action? Actions are meant to act somehow (update something in the database, invoke a web service, etc). If you just need to generate content, a Generator class could be a better fit for you...

Anyway... How could you return something from an Action into HTML? Lets see it with an example:

Action class: because it extends Action, it must return a Map. Just add there whatever data you need to pass to your HTML:

package com.stackoverflow;
public class ActionClass extends Action {
    public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters params) {
        Map<String, String> sitemapParams = new HashMap<String, String>();
        sitemapParams.put("myVariable", "hello world!");
        return sitemapParams;
    }
}

sitemap.xmap: in your sitemap file, you can access any data returned by the Action, by placing it's key between brackets. Then you can pass it to your HTML generator:

<map:components>
    <map:actions>
        <map:action name="myAction" src="com.stackoverflow.ActionClass" />
    </map:actions>
</map:components>
...
<map:match ...>
    <map:generate ... />
    <map:act type="myAction">
        <map:transform src="myTransformation.xsl">
            <map:parameter name="something" value="{myVariable}"/>
        </map:transform>
    </map:act>
    <map:serialize .../>
</map:match>

myTransformation.xsl: your XSLT file should read the data and embed it into your HTML:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:param name="something" select="'default value if you wish to specify one'"/>

    <xsl:template match="xxx">
        <html><body>...
            <xsl:value-of select="$something" />
        ...</body></html>
    </xsl:template>
</xsl:stylesheet>

You can get more information about Actions, Generators and the sitemap in this page. It's from Apache Cocoon 2.1 documentation, but it also applies to 2.2.


Alternative approach, with a Generator:

Generator class: this file builds a XML document, which is then passed into the pipeline. You could have something like this:

import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
...

public class GeneratorClass extends AbstractGenerator {

    private String foo;

    @Override
    public void setup(SourceResolver resolver, Map objectModel, String src, Parameters params) throws ProcessingException, SAXException, IOException {
        super.setup(resolver, objectModel, src, params);
        // you can read input parameters in here:
        foo = params.getParameter("someParameter");
    }

    public void generate() throws IOException, SAXException, ProcessingException {
        ArrayList<ResultBean> beans = xQuery(foo);

        // Let's build the XML document. I'll do it by manually appending text strings,
        // but there is no need, we could just use Xstream or any similar library
        StringBuilder xml = new StringBuilder();
        xml.append("<results>");

        // Iterate through the array list...
        for (ResultBean b : beans) {
            xml.append("<result>");
            xml.append("<id>").append(b.getId()).append("</id>");
            xml.append("<title>").append(b.getTitle()).append("</title>");
            xml.append("</result>");
        }

        // ... and we end the XML string
        xml.append("</results>");

        // Return the XML to Cocoon's pipeline
        XMLReader xmlreader = XMLReaderFactory.createXMLReader();
        xmlreader.setContentHandler(super.xmlConsumer);
        InputSource source = new InputSource(new StringReader(xml.toString()));
        xmlreader.parse(source);
        try {
            this.finalize();
        } catch (Throwable e) {
        }
    }

}

Sitemap.xmap: you just need to call your generator, and then apply your XSLT to the generated XML:

<map:components>
    <map:generators>
        <map:generator type="myGenerator" src="com.stackoverflow.GeneratorClass" />
    </map:generators>
/<map:components>

<map:generate type="myGenerator">
    <!-- if you need to pass input data to the generator... -->
    <map:parameter name="someParameter" select="{request-param:something}" />
</map:generate>
<map:transform src="myTransformation.xsl" />
<map:serialize type="html"/>

myTransformation.xsl:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
    <html>
        <head></head>
        <body>
            <table>
                <xsl:for-each select="results/result">
                    <tr>
                        <td><xsl:value-of select="id/text()"/></td>
                        <td><xsl:value-of select="title/text()"/></td>
                    </tr>
                </xsl:for-each>
            </table>
        </body>
    </html>
</xsl:template>

You can get more info about Cocoon generators here. Once again, it's an official tutorial for Cocoon 2.1, but it's also valid for Cocoon 2.2.

Другие советы

I'm trying to do something like this and it seems to work:

    <map:pipeline id="pd-version">
      <map:match pattern="pd/*/*">
        <map:aggregate element="foo">
            <map:part src="cocoon:/version-{1}-{2}.xml"/>
            <map:part src="http://localhost:8888/GRLegislation/pd/{1}/{2}/data.xml"/>
        </map:aggregate>
        <map:transform src="legislation_updated.xslt" type="xslt-saxon"/>
        <map:transform src="legislation.xslt" type="xslt-saxon">
        </map:transform>
        <map:serialize type="xhtml"/>
      </map:match>
    </map:pipeline>

    <map:pipeline>
    <map:match pattern="version-*-*">
      <map:generate type="versiongen">
            <map:parameter name="type" value="pd"/>
            <map:parameter name="year" value="{1}"/>
            <map:parameter name="id" value="{2}"/>        
      </map:generate>
      <map:serialize type="xml"/> 
    </map:match> 
    </map:pipeline>

Parameters are not loaded correctly from <map:part> to <map:match>. Also I have some XSLT issues, because now we have a different root of XML.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top