Hi all,
I've tried to use the new namespace-aware Configurations and encountered
serious problems : each Configuration is given the latest namespaces
declared whatever its actual namespace is.
For example :
<?xml version='1.0'?>
<ns2:config xmlns:ns1='namespace-1' xmlns:ns2='namespace-2'>
<ns1:child name='child-config'>
<foo>value of blah</foo>
</ns1:child>
</ns2:config>
leads to all elements being marked as belonging to "ns2" (the latest one
declared).
So please find attached a patch for both SAXConfigurationHandler and
DefaultConfigurationSerializer.
But there's another important issue : configurations are given the
prefixed name of the XML element (e.g. "ns2:config" and "ns1:child"). I
think this is wrong : namespace prefix is only XML syntactic sugar and
doesn't have any semantic meaning (you can give any prefix to a
namespace). Having prefixed names obliges either the configuration file
to use predefined XML prefixes (we've seen on Cocoon how error prone
this can be) or the application to manually strip prefixes when
processing the configuration.
What I propose is that a Configuration object is given the local XML
element name (no prefix) and only has the URI as namespace information.
The Namespace class could even be removed.
The only use I can see for the prefix is for XML serialization. We could
either :
- have the serializer auto-generate prefixes (ns1, ns2, etc), possibly
with the help of a Map of default prefix/URI mappings,
- keep prefixes in Configuration only as a serialization hint. But
application code using Configuration objects shouldn't have to worry
about it, meaning as above automatic prefix generation for
Configurations created by the application.
Thoughts ?
--
Sylvain Wallez
Anyware Technologies - http://www.anyware-tech.com
? config.diff
Index: DefaultConfigurationSerializer.java
===================================================================
RCS file:
/home/cvspublic/jakarta-avalon/src/java/org/apache/avalon/framework/configuration/DefaultConfigurationSerializer.java,v
retrieving revision 1.2
diff -u -r1.2 DefaultConfigurationSerializer.java
--- DefaultConfigurationSerializer.java 2001/10/02 16:24:55 1.2
+++ DefaultConfigurationSerializer.java 2001/10/29 13:40:14
@@ -14,6 +14,7 @@
import java.net.URL;
import java.util.Properties;
import org.xml.sax.helpers.AttributesImpl;
+import org.xml.sax.helpers.NamespaceSupport;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import javax.xml.transform.OutputKeys;
@@ -35,7 +36,7 @@
private TransformerHandler m_handler;
private OutputStream m_out;
private Properties m_format = new Properties();
- private Namespace m_currentNamespace = Namespace.getNamespace(
null );
+ private NamespaceSupport m_namespaceSupport = new NamespaceSupport();
/**
* Build a ConfigurationSerializer
@@ -83,6 +84,7 @@
protected void serialize( final Configuration source )
throws SAXException
{
+ this.m_namespaceSupport.reset();
this.m_handler.startDocument();
this.serializeElement(source);
this.m_handler.endDocument();
@@ -94,6 +96,8 @@
protected void serializeElement( final Configuration element )
throws SAXException
{
+ m_namespaceSupport.pushContext();
+
AttributesImpl attr = new AttributesImpl();
String[] attrNames = element.getAttributeNames();
@@ -101,20 +105,38 @@
{
for (int i = 0; i < attrNames.length; i++)
{
- attr.setAttribute(i, "", attrNames[i], attrNames[i], "CDATA",
+ attr.addAttribute("", attrNames[i], attrNames[i], "CDATA",
element.getAttribute(attrNames[i], ""));
}
}
- Namespace oldNamespace = null;
- if ( m_currentNamespace != element.getNamespace() )
+ final Namespace namespace = element.getNamespace();
+ final String nsURI = namespace.getURI();
+ final String nsPrefix = namespace.getPrefix();
+ boolean nsWasDeclared = false;
+
+ // Is this namespace already declared ?
+ final String existingUri = m_namespaceSupport.getURI( nsPrefix );
+ if ( existingUri == null || !existingUri.equals( nsURI ) )
+ {
+ nsWasDeclared = true;
+ this.m_handler.startPrefixMapping( nsPrefix, nsURI );
+ this.m_namespaceSupport.declarePrefix( nsPrefix, nsURI );
+ }
+
+ String qName = element.getName();
+ String localName;
+ if ( nsPrefix == null || nsPrefix.length() == 0)
{
- oldNamespace = m_currentNamespace;
- m_currentNamespace = element.getNamespace();
- this.m_handler.startPrefixMapping( m_currentNamespace.getPrefix(),
m_currentNamespace.getURI() );
+ localName = qName;
}
-
- this.m_handler.startElement("", element.getName(), element.getName(),
attr);
+ else
+ {
+ localName = qName.substring( nsPrefix.length() + 1 );
+ }
+
+ this.m_handler.startElement(nsURI, localName, qName, attr);
+
String value = element.getValue(null);
if (null == value)
@@ -131,13 +153,14 @@
this.m_handler.characters(value.toCharArray(), 0, value.length());
}
- this.m_handler.endElement("", element.getName(), element.getName());
+ this.m_handler.endElement(nsURI, localName, qName);
- if ( null != oldNamespace )
+ if ( nsWasDeclared )
{
- this.m_handler.endPrefixMapping( m_currentNamespace.getPrefix() );
- m_currentNamespace = oldNamespace;
+ this.m_handler.endPrefixMapping( nsPrefix );
}
+
+ this.m_namespaceSupport.popContext();
}
/**
Index: SAXConfigurationHandler.java
===================================================================
RCS file:
/home/cvspublic/jakarta-avalon/src/java/org/apache/avalon/framework/configuration/SAXConfigurationHandler.java,v
retrieving revision 1.5
diff -u -r1.5 SAXConfigurationHandler.java
--- SAXConfigurationHandler.java 2001/10/02 16:24:55 1.5
+++ SAXConfigurationHandler.java 2001/10/29 13:40:15
@@ -8,13 +8,13 @@
package org.apache.avalon.framework.configuration;
import java.util.ArrayList;
-import java.util.Stack;
import org.xml.sax.Attributes;
import org.xml.sax.ErrorHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;
+import org.xml.sax.helpers.NamespaceSupport;
/**
* A SAXConfigurationHandler helps build Configurations out of sax events.
@@ -29,7 +29,7 @@
private final ArrayList m_elements = new ArrayList();
private Configuration m_configuration;
private Locator m_locator;
- private Stack m_namespaceStack = new Stack();
+ protected NamespaceSupport m_namespaceSupport = new
NamespaceSupport();
public Configuration getConfiguration()
{
@@ -50,15 +50,14 @@
public void startDocument()
throws SAXException
{
- m_namespaceStack.push(Namespace.getNamespace(null));
+ m_namespaceSupport.reset();
super.startDocument();
}
public void endDocument()
throws SAXException
{
- super.endDocument();
- m_namespaceStack.clear();
+ m_namespaceSupport.reset();
}
public void characters( final char[] ch, int start, int end )
@@ -97,12 +96,19 @@
{
m_configuration = (Configuration)object;
}
+
+ m_namespaceSupport.popContext();
}
protected DefaultConfiguration createConfiguration( final String localName,
+ final String
namespaceURI,
final String location )
{
- return new DefaultConfiguration( localName, location, (Namespace)
this.m_namespaceStack.peek() );
+ final String prefix = m_namespaceSupport.getPrefix( namespaceURI
);
+ final Namespace namespace = Namespace.getNamespace( prefix,
namespaceURI );
+ final String name = (prefix == null) ? localName : prefix +
":" + localName;
+
+ return new DefaultConfiguration( name, location, namespace );
}
public void startElement( final String namespaceURI,
@@ -111,8 +117,10 @@
final Attributes attributes )
throws SAXException
{
+ m_namespaceSupport.pushContext();
+
final DefaultConfiguration configuration =
- createConfiguration( rawName, getLocationString() );
+ createConfiguration( localName, namespaceURI, getLocationString()
);
final int size = m_elements.size() - 1;
if( size > -1 )
@@ -187,18 +195,6 @@
public void startPrefixMapping(String prefix, String uri)
throws SAXException
{
- m_namespaceStack.push( Namespace.getNamespace( prefix, uri ) );
- super.startPrefixMapping( prefix, uri );
- }
-
- public void endPrefixMapping(String prefix)
- throws SAXException
- {
- Namespace ns = (Namespace) m_namespaceStack.pop();
- if ( !( ns.getPrefix().equals( prefix ) ) )
- {
- throw new SAXException( "Uneven namespace mapping for prefix: " +
prefix );
- }
- super.endPrefixMapping( prefix );
+ m_namespaceSupport.declarePrefix( prefix, uri );
}
}
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>