Overview

This How-To shows you how to use Xindice as the repository for XML resources from the XMLForm Framework. It requires prior knowledge of Cocoon XMLForm, XSLT, Schematron, Xindice and the XMLDB API.

Purpose

You will learn how to build a simple wizard type XMLForm that stores XML data into a Xindice collection.

Intended Audience

Cocoon users who want to learn how to store data obtained from XMLForms into Xindice.

Prerequisites

Cocoon must be running on your system. The steps below have been tested with Cocoon 2.1-dev. You will need the following:

build -Dinclude.webapp.libs=true webapp You will need to understand and be familiar with XSL, XForms, XPath, Schematron and Xindice. Some knowledge about the XMLDB API would be helpful, too. If you are unfamiliar with these technologies, it is advised that you learn these related concepts first. If you are unfamiliar with XMLForm, check out theXMLForm Wizard How-To first.

Steps

We will follow the needed steps in order to add a document like this:

{{{<Artist id="pearljam">

</Artist>}}} to the Xindice root collection. We will get the identifier and name data using a XMLForm and store them in Xindice. We will build this XMLForm very similar to the one in the XMLForm Wizard How-To.

Building the XMLForm files

Create the files and name them as specified below.

start.xform

{{{<?xml version="1.0"?> <document>

</document>}}}

artist.xform

{{{<?xml version="1.0"?> <document

</document>}}}

end.xform

{{{<?xml version="1.0"?> <document>

</document>}}}

error.xform

{{{<?xml version="1.0"?>

</document>}}}

Validation

For the sake of simplicity we just validate one property against one condition. We require the identifier to be at least two characters in length; the validation file, artist-validator.xml is as follows: {{{<?xml version="1.0"?> <schema ns="http://xml.apache.cocoon/xmlform"

</schema>}}}

Extended Validation

There could be more complicated rules in Schematron but we could also require the identifier to be unique in the database. In this case we should query the database and see if it already exists. If so, a new violation can be added to the form. Since these kinds of violations are out of the scope of Schematron, these operations should be accomplished in the Action using Java code.

Model Bean

Persistence for the data will be accomplished by this bean. In order to store the mentioned XML structure we will use a DOM Node. You can also try JXPath Containers as suggested by Ivelin. The model bean ArtistBean.java is as follows: {{{package com.simbiosystems.cocoon.xmlform.xindice.howto;

import java.util.ArrayList; import java.util.List;

import org.w3c.dom.*; import javax.xml.parsers.*; import javax.xml.transform.*;

/**

public class ArtistBean {

} }}}

The Action

In this Action we have integrated the Xindice handling code, getting the data from the model (from the DOM Node property) and storing it in Xindice. The Action that controls this form is ArtistAction.java: {{{package com.simbiosystems.cocoon.xmlform.xindice.howto;

import java.util.Arrays; import java.util.Enumeration; import java.util.Map;

import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.apache.avalon.framework.parameters.Parameters; import org.apache.cocoon.Constants; import org.apache.cocoon.acting.AbstractXMLFormAction; import org.apache.cocoon.components.validation.Violation; import org.apache.cocoon.components.xmlform.Form; import org.apache.cocoon.components.xmlform.FormListener; import org.apache.cocoon.environment.Redirector; import org.apache.cocoon.environment.Request; import org.apache.cocoon.environment.Session; import org.apache.cocoon.environment.SourceResolver; import org.w3c.dom.DOMImplementation; import org.w3c.dom.Node;

import com.simbiosystems.cocoon.xmlform.xindice.howto.XindiceManager;

/**

public class ArtistAction extends AbstractXMLFormAction implements FormListener {

} }}}

The helper class

In order to make this work we need to use a helper class. This class uses the XMLDB to connect to Xindice and make the operations available to the Action. You should extend it to add more operations. The helper class XindiceManager.java is as follows: {{{/**

package com.simbiosystems.cocoon.xmlform.xindice.howto;

import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.DOMImplementation; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.xmldb.api.DatabaseManager; import org.xmldb.api.base.Collection; import org.xmldb.api.base.Database; import org.xmldb.api.base.Resource; import org.xmldb.api.base.ResourceIterator; import org.xmldb.api.base.ResourceSet; import org.xmldb.api.base.XMLDBException; import org.xmldb.api.modules.XMLResource; import org.xmldb.api.modules.XPathQueryService;

public class XindiceManager {

} }}}

The Sitemap

Remember you should have the XML!FormTransformer defined like this: {{{<map:transformer name="xmlform" src="org.apache.cocoon.transformation.XMLFormTransformer" logger="xmlform"/>}}} Then, you must declare the Action to be used in the correspondent section: <map:action logger="xmlform" name="ArtistAction" src="com.simbiosystems.cocoon.xmlform.xindice.howto.ArtistAction"/>

The Pipeline

{{{<!-- XMLForms pipeline --> <map:pipeline>

</map:pipeline>}}} Depending on where you have Cocoon installed and where you have configured the files in this howto, you could make a request to a URL like http://localhost:8080/cocoon/Artist.xform and start using the Form.

Final Considerations

Making the operations from the Action using the helper class seems to be the easiest way. You can think of other ways or other operations using other Xindice tools available in Cocoon such as the pseudo protocol. For example, you could use it to query the DB for data that could be stored in a sitemap parameter. You could then get the data from the Action and use it to fill a selectbox in the form.
We did not mentioned other operations such as updates. This can be also accomplished this way. For example, if you want to edit the data we just stored, you could load it in the DOM Node at the beginning by using the find method of the helper class. This way you get a filled form in the next step ready for editing. Other ways or interacting with the repository include the XMLDB Transformer. Since it uses XUpdate alike syntax, you could format a XML String for it in the last step of the Action, making it available to the sitemap then, so the Transformer could get it and make the operations.
I'm sure you can think of more different ways. I encourage you to contribute them if you have tested it succesfully.

Summary

This How-To makes possible the use of Xindice from XMLForms in order to add data to the repository. You learned how to connect to the DB from the Action, and how to make complex validation using information stored in the DB. I hope it was helpful for you.

XMLFormXindiceOldVersion (last edited 2009-09-20 23:40:03 by localhost)