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