Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>If the origin is XML, I suggest to go for a completely different approach: <a href="http://www.w3schools.com/xml/xsl_intro.asp" rel="nofollow noreferrer">XSL</a>. Facelets is XHTML based. You can easily use XSL to go from XML to XHTML. This is doable with a bit decent <code>Filter</code> which kicks in before JSF is doing the works.</p> <p>Here's a kickoff example.</p> <p><code>persons.xml</code></p> <pre class="lang-xml prettyprint-override"><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt; &lt;persons&gt; &lt;person&gt; &lt;name&gt;one&lt;/name&gt; &lt;age&gt;1&lt;/age&gt; &lt;/person&gt; &lt;person&gt; &lt;name&gt;two&lt;/name&gt; &lt;age&gt;2&lt;/age&gt; &lt;/person&gt; &lt;person&gt; &lt;name&gt;three&lt;/name&gt; &lt;age&gt;3&lt;/age&gt; &lt;/person&gt; &lt;/persons&gt; </code></pre> <p><code>persons.xsl</code></p> <pre class="lang-xml prettyprint-override"><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt; &lt;xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html"&gt; &lt;xsl:output method="xml" doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"/&gt; &lt;xsl:template match="persons"&gt; &lt;html&gt; &lt;f:view&gt; &lt;head&gt;&lt;title&gt;Persons&lt;/title&gt;&lt;/head&gt; &lt;body&gt; &lt;h:panelGrid columns="2"&gt; &lt;xsl:for-each select="person"&gt; &lt;xsl:variable name="name"&gt;&lt;xsl:value-of select="name" /&gt;&lt;/xsl:variable&gt; &lt;xsl:variable name="age"&gt;&lt;xsl:value-of select="age" /&gt;&lt;/xsl:variable&gt; &lt;h:outputText value="{$name}" /&gt; &lt;h:outputText value="{$age}" /&gt; &lt;/xsl:for-each&gt; &lt;/h:panelGrid&gt; &lt;/body&gt; &lt;/f:view&gt; &lt;/html&gt; &lt;/xsl:template&gt; &lt;/xsl:stylesheet&gt; </code></pre> <p><code>JsfXmlFilter</code> which is mapped on <code>&lt;servlet-name&gt;</code> of the <code>FacesServlet</code> and assumes that the <code>FacesServlet</code> itself is mapped on an <code>&lt;url-pattern&gt;</code> of <code>*.jsf</code>.</p> <pre><code>public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest r = (HttpServletRequest) request; String rootPath = r.getSession().getServletContext().getRealPath("/"); String uri = r.getRequestURI(); String xhtmlFileName = uri.substring(uri.lastIndexOf("/")).replaceAll("jsf$", "xhtml"); // Change this if FacesServlet is not mapped on `*.jsf`. File xhtmlFile = new File(rootPath, xhtmlFileName); if (!xhtmlFile.exists()) { // Do your caching job. String xmlFileName = xhtmlFileName.replaceAll("xhtml$", "xml"); String xslFileName = xhtmlFileName.replaceAll("xhtml$", "xsl"); File xmlFile = new File(rootPath, xmlFileName); File xslFile = new File(rootPath, xslFileName); Source xmlSource = new StreamSource(xmlFile); Source xslSource = new StreamSource(xslFile); Result xhtmlResult = new StreamResult(xhtmlFile); try { Transformer transformer = TransformerFactory.newInstance().newTransformer(xslSource); transformer.transform(xmlSource, xhtmlResult); } catch (TransformerException e) { throw new RuntimeException("Transforming failed.", e); } } chain.doFilter(request, response); } </code></pre> <p>Run by <a href="http://example.com/context/persons.jsf" rel="nofollow noreferrer">http://example.com/context/persons.jsf</a> and this filter will kick in and transform <code>persons.xml</code> to <code>persons.xhtml</code> using <code>persons.xsl</code> and finally put <code>persons.xhtml</code> there where JSF expect it is.</p> <p>True, XSL has a bit of learning curve, but it's IMO the right tool for the job since the source is XML and destination is XML based as wel.</p> <p>To do the mapping between the form and the managed bean, just use a <code>Map&lt;String, Object&gt;</code>. If you name the input fields like so</p> <pre class="lang-xml prettyprint-override"><code>&lt;h:inputText value="#{bean.map.field1}" /&gt; &lt;h:inputText value="#{bean.map.field2}" /&gt; &lt;h:inputText value="#{bean.map.field3}" /&gt; ... </code></pre> <p>The submitted values will be available by <code>Map</code> keys <code>field1</code>, <code>field2</code>, <code>field3</code>, etc.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload