Author: gianugo Date: Wed Dec 29 10:28:30 2004 New Revision: 123668 URL: http://svn.apache.org/viewcvs?view=rev&rev=123668 Log: Enable binding on namespaced XML. Work is still incomplete, and JXPath has quite a nasty bug preventing full funtionality, but hey, it's a start!
Added: cocoon/branches/BRANCH_2_1_X/src/blocks/forms/samples/forms/binding/06namespaced-bind.xml cocoon/branches/BRANCH_2_1_X/src/blocks/forms/samples/forms/binding/06namespaced-data.xml cocoon/branches/BRANCH_2_1_X/src/blocks/forms/samples/forms/binding/06namespaced-def.xml Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/binding/JXPathBindingBase.java cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/binding/JXPathBindingBuilderBase.java cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/util/DomHelper.java cocoon/branches/BRANCH_2_1_X/src/blocks/forms/samples/welcome.xml Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/binding/JXPathBindingBase.java Url: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/binding/JXPathBindingBase.java?view=diff&rev=123668&p1=cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/binding/JXPathBindingBase.java&r1=123667&p2=cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/binding/JXPathBindingBase.java&r2=123668 ============================================================================== --- cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/binding/JXPathBindingBase.java (original) +++ cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/binding/JXPathBindingBase.java Wed Dec 29 10:28:30 2004 @@ -16,6 +16,7 @@ package org.apache.cocoon.forms.binding; import java.util.HashMap; +import java.util.Iterator; import java.util.Map; import org.apache.avalon.framework.logger.LogEnabled; @@ -149,12 +150,15 @@ throws BindingException { boolean inheritedLeniency = jxpc.isLenient(); applyLeniency(jxpc); + applyNSDeclarations(jxpc); if (this.commonAtts.loadEnabled) { doLoad(frmModel, jxpc); } jxpc.setLenient(inheritedLeniency); } + + /** * Hooks up with the more generic Binding of any objectModel by wrapping * it up in a JXPathContext object and then transfering control over to @@ -188,6 +192,7 @@ throws BindingException{ boolean inheritedLeniency = jxpc.isLenient(); applyLeniency(jxpc); + applyNSDeclarations(jxpc); if (this.commonAtts.saveEnabled) { doSave(frmModel, jxpc); } @@ -216,6 +221,21 @@ } } + private void applyNSDeclarations(JXPathContext jxpc) + { + if (this.commonAtts.nsDeclarations != null) + { + Iterator keysIter = this.commonAtts.nsDeclarations.keySet().iterator(); + while (keysIter.hasNext()) + { + String nsuri = (String) keysIter.next(); + String pfx = (String) this.commonAtts.nsDeclarations.get(nsuri); + jxpc.registerNamespace(pfx, nsuri); + } + } + } + + private JXPathContext makeJXPathContext(Object objModel) { JXPathContext jxpc; if (!(objModel instanceof JXPathContext)) { Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/binding/JXPathBindingBuilderBase.java Url: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/binding/JXPathBindingBuilderBase.java?view=diff&rev=123668&p1=cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/binding/JXPathBindingBuilderBase.java&r1=123667&p2=cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/binding/JXPathBindingBuilderBase.java&r2=123668 ============================================================================== --- cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/binding/JXPathBindingBuilderBase.java (original) +++ cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/binding/JXPathBindingBuilderBase.java Wed Dec 29 10:28:30 2004 @@ -15,6 +15,8 @@ */ package org.apache.cocoon.forms.binding; +import java.util.Map; + import org.apache.avalon.framework.logger.LogEnabled; import org.apache.avalon.framework.logger.Logger; import org.apache.cocoon.forms.util.DomHelper; @@ -109,7 +111,22 @@ String leniency = DomHelper.getAttribute(bindingElm, "lenient", null); - return new CommonAttributes(direction, leniency); + //TODO: current jxpath is not inheriting registered namespaces over to + // child-relative jxpath contexts --> because of that we can't just + // remember the getLocalNSDeclarations but need the full set from + // getInheritedNSDeclarations + // IMPORTANT NOTE: if jxpath would change this behaviour we would however + // still need to be able to unregister namespace-declarations + // (in a smart way: unhide what is possably available from your parent. + // So both changes to jxpath need to be available before changing the below. + Map nsDeclarationMap = DomHelper.getInheritedNSDeclarations(bindingElm); + // we (actually jxpath) doesn't support un-prefixed namespace-declarations: + // so we decide to break on those above silently ignoring them + if (nsDeclarationMap != null && nsDeclarationMap.values().contains(null)) + throw new BindingException("Error in binding file " + DomHelper.getLocation(bindingElm) + + "\nBinding doesn't support having namespace-declarations without explicit prefixes."); + + return new CommonAttributes(direction, leniency, nsDeclarationMap); } catch (BindingException e) { throw e; } catch (Exception e) { @@ -131,18 +148,27 @@ * Flag which controls whether a binding is active during saving. */ final boolean saveEnabled; + /** + * Flag which controls whether the jxpath context used by this binding + * should be operating in lenient mode or not + */ final Boolean leniency; + /** + * Array of namespace-declarations (prefix-uri pairs) that need to be set on the jxpath + */ + final Map nsDeclarations; - final static CommonAttributes DEFAULT = new CommonAttributes(true, true, null); + final static CommonAttributes DEFAULT = new CommonAttributes(true, true, null, null); - CommonAttributes(String direction, String leniency){ - this(isLoadEnabled(direction), isSaveEnabled(direction), decideLeniency(leniency)); + CommonAttributes(String direction, String leniency, Map nsDeclarations){ + this(isLoadEnabled(direction), isSaveEnabled(direction), decideLeniency(leniency), nsDeclarations); } - CommonAttributes(boolean loadEnabled, boolean saveEnabled, Boolean leniency){ + CommonAttributes(boolean loadEnabled, boolean saveEnabled, Boolean leniency, Map nsDeclarations){ this.loadEnabled = loadEnabled; this.saveEnabled = saveEnabled; this.leniency = leniency; + this.nsDeclarations = nsDeclarations; } /** Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/util/DomHelper.java Url: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/util/DomHelper.java?view=diff&rev=123668&p1=cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/util/DomHelper.java&r1=123667&p2=cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/util/DomHelper.java&r2=123668 ============================================================================== --- cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/util/DomHelper.java (original) +++ cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/util/DomHelper.java Wed Dec 29 10:28:30 2004 @@ -17,6 +17,11 @@ import java.io.IOException; import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; import org.apache.avalon.framework.service.ServiceException; import org.apache.avalon.framework.service.ServiceManager; @@ -33,9 +38,11 @@ import org.apache.xerces.xni.XMLAttributes; import org.apache.xerces.xni.XMLLocator; import org.apache.xerces.xni.XNIException; +import org.w3c.dom.Attr; import org.w3c.dom.CDATASection; import org.w3c.dom.Document; import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.Text; @@ -58,6 +65,8 @@ */ public class DomHelper { + public static final String XMLNS_URI = "http://www.w3.org/2000/xmlns/"; + /** * Retrieves the location of an element node in the source file from which * the Document was created. This will only work for Document's created @@ -390,5 +399,54 @@ node.setUserData("location", location, null); } } + } + + public static Map getLocalNSDeclarations(Element elm) + { + return addLocalNSDeclarations(elm, null); + } + + private static Map addLocalNSDeclarations(Element elm, Map nsDeclarations) + { + NamedNodeMap atts = elm.getAttributes(); + int attsSize = atts.getLength(); + + for (int i = 0; i < attsSize; i++) + { + Attr attr = (Attr)atts.item(i); + if (XMLNS_URI.equals(attr.getNamespaceURI())) + { + String nsUri = attr.getValue(); + String pfx = attr.getLocalName(); + if (nsDeclarations == null) + nsDeclarations = new HashMap(); + nsDeclarations.put(nsUri, pfx); + } + } + return nsDeclarations; } + + public static Map getInheritedNSDeclarations(Element elm) + { + List ancestorsAndSelf = new LinkedList(); + Element current = elm; + while (current != null) + { + ancestorsAndSelf.add(current); + Node parent = current.getParentNode(); + if (parent.getNodeType() == Node.ELEMENT_NODE) + current = (Element)parent; + else + current = null; + } + + Map nsDeclarations = null; + ListIterator iter = ancestorsAndSelf.listIterator(ancestorsAndSelf.size()); + while (iter.hasPrevious()) + { + Element element = (Element) iter.previous(); + nsDeclarations = addLocalNSDeclarations(element, nsDeclarations); + } + + return nsDeclarations; } } Added: cocoon/branches/BRANCH_2_1_X/src/blocks/forms/samples/forms/binding/06namespaced-bind.xml Url: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/forms/samples/forms/binding/06namespaced-bind.xml?view=auto&rev=123668 ============================================================================== --- (empty file) +++ cocoon/branches/BRANCH_2_1_X/src/blocks/forms/samples/forms/binding/06namespaced-bind.xml Wed Dec 29 10:28:30 2004 @@ -0,0 +1,39 @@ +<?xml version="1.0"?> +<!-- + Copyright 1999-2004 The Apache Software Foundation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<fb:context xmlns:fb="http://apache.org/cocoon/forms/1.0#binding" + xmlns:fd="http://apache.org/cocoon/forms/1.0#definition" + xmlns:h="http://www.w3.org/1999/xhtml" + path="/" > + +<!-- + | This file binds form data to a namespaced XML + --> + + <fb:context path="h:html/h:head" > + <fb:value id="title" path="html:title" lenient="true" /> + </fb:context> + + <fb:context path="x:stylesheet" xmlns:x="http://www.w3.org/1999/XSL/Transform"> + <fb:value id="template" path="x:template/@name" lenient="true"/> + </fb:context> + + <fb:context path="." xmlns:f="http://www.w3.org/1999/XSL/Format"> + <fb:value id="flowname" path="f:root/f:page-sequence/f:flow/@flow-name" lenient="true"/> + </fb:context> + +</fb:context> Added: cocoon/branches/BRANCH_2_1_X/src/blocks/forms/samples/forms/binding/06namespaced-data.xml Url: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/forms/samples/forms/binding/06namespaced-data.xml?view=auto&rev=123668 ============================================================================== --- (empty file) +++ cocoon/branches/BRANCH_2_1_X/src/blocks/forms/samples/forms/binding/06namespaced-data.xml Wed Dec 29 10:28:30 2004 @@ -0,0 +1,29 @@ +<?xml version="1.0"?> +<!-- + Copyright 1999-2004 The Apache Software Foundation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<test> + <html:html xmlns:html="http://www.w3.org/1999/xhtml"> + <html:head> + <html:title>some title</html:title> + </html:head> + </html:html> + <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> + <xsl:template name="template-name"/> + </xsl:stylesheet> + <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> + <fo:page-sequence><fo:flow flow-name="flow-name" /></fo:page-sequence> + </fo:root> +</test> Added: cocoon/branches/BRANCH_2_1_X/src/blocks/forms/samples/forms/binding/06namespaced-def.xml Url: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/forms/samples/forms/binding/06namespaced-def.xml?view=auto&rev=123668 ============================================================================== --- (empty file) +++ cocoon/branches/BRANCH_2_1_X/src/blocks/forms/samples/forms/binding/06namespaced-def.xml Wed Dec 29 10:28:30 2004 @@ -0,0 +1,35 @@ +<?xml version="1.0"?> +<!-- + Copyright 1999-2004 The Apache Software Foundation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<fd:form + xmlns:fd="http://apache.org/cocoon/forms/1.0#definition" + xmlns:i18n="http://apache.org/cocoon/i18n/2.1"> + + <fd:widgets> + <fd:field id="title"> + <fd:label>Enter an HTML title</fd:label> + <fd:datatype base="string" /> + </fd:field> + <fd:field id="template"> + <fd:label>Enter an XSL template name</fd:label> + <fd:datatype base="string" /> + </fd:field> + <fd:field id="flowname"> + <fd:label>And now a XSL:FO flow name</fd:label> + <fd:datatype base="string" /> + </fd:field> + </fd:widgets> +</fd:form> Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/forms/samples/welcome.xml Url: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/forms/samples/welcome.xml?view=diff&rev=123668&p1=cocoon/branches/BRANCH_2_1_X/src/blocks/forms/samples/welcome.xml&r1=123667&p2=cocoon/branches/BRANCH_2_1_X/src/blocks/forms/samples/welcome.xml&r2=123668 ============================================================================== --- cocoon/branches/BRANCH_2_1_X/src/blocks/forms/samples/welcome.xml (original) +++ cocoon/branches/BRANCH_2_1_X/src/blocks/forms/samples/welcome.xml Wed Dec 29 10:28:30 2004 @@ -58,6 +58,7 @@ <sample name="3. Aggregate Binding" href="binding-03aggregate.flow">fb:aggregate</sample> <sample name="4. Heavy Form" href="binding-04heavy-XML.flow">Form with lots of select boxes - test memory utilization, performance</sample> <sample name="5. Custom Bindings using Java or Javascript" href="binding-05custom.flow">fb:javascript and fb:custom</sample> + <sample name="6. XML binding using namespaces" href="binding-06namespaced-XML.flow">Using XML binding with complex namespaced XML</sample> <!-- TODO: provide more tutorial samples like these: <sample name="6. MultiValue/Repeater Binding" href="binding-03multi.flow">fb:multi-value</sample> <sample name="7. Repeater Binding" href="binding-06repeater.flow">fb:repeater</sample>