bruno 2003/03/11 07:40:54
Modified: src/java/org/apache/cocoon/xml/dom DOMStreamer.java
Log:
sync with 2.1
Revision Changes Path
1.3 +136 -39 cocoon-2.0/src/java/org/apache/cocoon/xml/dom/DOMStreamer.java
Index: DOMStreamer.java
===================================================================
RCS file: /home/cvs/cocoon-2.0/src/java/org/apache/cocoon/xml/dom/DOMStreamer.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- DOMStreamer.java 10 Mar 2003 15:42:39 -0000 1.2
+++ DOMStreamer.java 11 Mar 2003 15:40:54 -0000 1.3
@@ -341,8 +341,14 @@
String prefix = node.getPrefix();
String localName = node.getLocalName();
- if (localName == null)
- throw new SAXException("[NamespaceNormalizingDOMStreamer]
Encountered a DOM Element without a localName. DOM Level 1 trees are not supported by
this DOMStreamer.");
+ if (localName == null) {
+ // this is an element created with createElement instead of
createElementNS
+ String[] prefixAndLocalName =
getPrefixAndLocalName(node.getNodeName());
+ prefix = prefixAndLocalName[0];
+ localName = prefixAndLocalName[1];
+ // note: if prefix is null, there can still be a default
namespace...
+ namespaceURI = getNamespaceForPrefix(prefix, (Element)node);
+ }
if (namespaceURI != null) {
// no prefix means: make this the default namespace
@@ -387,45 +393,66 @@
for (int i = 0; i < nAttrs; i++) {
Node attr = atts.item(i);
String attrName = attr.getNodeName();
- String attrPrefix = null;
-
- if (attr.getLocalName() == null)
- throw new
SAXException("[NamespaceNormalizingDOMStreamer] Encountered an attribute without a
local name, this DOM streamer does not support that.");
+ String assignedAttrPrefix = null;
// only do non-namespace attributes
if (!(attrName.equals("xmlns") ||
attrName.startsWith("xmlns:"))) {
- if (attr.getNamespaceURI() != null) {
- String declaredUri =
currentElementInfo.findNamespaceURI(attr.getPrefix());
+ String attrPrefix;
+ String attrLocalName;
+ String attrNsURI;
+
+ if (attr.getLocalName() == null) {
+ // this is an attribute created with setAttribute
instead of setAttributeNS
+ String[] prefixAndLocalName =
getPrefixAndLocalName(attrName);
+ attrPrefix = prefixAndLocalName[0];
+ // the statement below causes the attribute to keep
its prefix even if it is not
+ // bound to a namespace (to support pre-namespace
XML).
+ assignedAttrPrefix = attrPrefix;
+ attrLocalName = prefixAndLocalName[1];
+ // note: if prefix is null, the attribute has no
namespace (namespace defaulting
+ // does not apply to attributes)
+ if (attrPrefix != null)
+ attrNsURI = getNamespaceForPrefix(attrPrefix,
(Element)node);
+ else
+ attrNsURI = null;
+ } else {
+ attrLocalName = attr.getLocalName();
+ attrPrefix = attr.getPrefix();
+ attrNsURI = attr.getNamespaceURI();
+ }
+
+ if (attrNsURI != null) {
+ String declaredUri =
currentElementInfo.findNamespaceURI(attrPrefix);
// if the prefix is null, or the prefix has not
been declared, or conflicts with an in-scope binding
- if (declaredUri == null ||
!declaredUri.equals(attr.getNamespaceURI())) {
- String availablePrefix =
currentElementInfo.findPrefix(attr.getNamespaceURI());
+ if (declaredUri == null ||
!declaredUri.equals(attrNsURI)) {
+ String availablePrefix =
currentElementInfo.findPrefix(attrNsURI);
if (availablePrefix != null)
- attrPrefix = availablePrefix;
+ assignedAttrPrefix = availablePrefix;
else {
- if (attr.getPrefix() != null && declaredUri
== null) {
+ if (attrPrefix != null && declaredUri ==
null) {
// prefix is not null and is not yet
declared: declare it
- attrPrefix = attr.getPrefix();
- currentElementInfo.put(attrPrefix,
attr.getNamespaceURI());
+ assignedAttrPrefix = attrPrefix;
+
currentElementInfo.put(assignedAttrPrefix, attrNsURI);
} else {
// attribute has no prefix (which is
not allowed for namespaced attributes) or
// the prefix is already bound to
something else: generate a new prefix
newPrefixCounter++;
- attrPrefix = "NS" + newPrefixCounter;
- currentElementInfo.put(attrPrefix,
attr.getNamespaceURI());
+ assignedAttrPrefix = "NS" +
newPrefixCounter;
+
currentElementInfo.put(assignedAttrPrefix, attrNsURI);
}
}
} else {
- attrPrefix = attr.getPrefix();
+ assignedAttrPrefix = attrPrefix;
}
}
- String attrNamespaceURI = attr.getNamespaceURI() !=
null ? attr.getNamespaceURI() : "";
+ String assignedAttrNsURI = attrNsURI != null ?
attrNsURI : "";
String attrQName;
- if (attrPrefix != null)
- attrQName = attrPrefix + ":" + attr.getLocalName();
+ if (assignedAttrPrefix != null)
+ attrQName = assignedAttrPrefix + ":" +
attrLocalName;
else
- attrQName = attr.getLocalName();
- newAttrs.addAttribute(attrNamespaceURI,
attr.getLocalName(), attrQName, "CDATA", attr.getNodeValue());
+ attrQName = attrLocalName;
+ newAttrs.addAttribute(assignedAttrNsURI, attrLocalName,
attrQName, "CDATA", attr.getNodeValue());
}
}
@@ -440,7 +467,7 @@
String qn = pr.equals("") ? "xmlns" : "xmlns:" + pr;
newAttrs.addAttribute("", pr1, qn, "CDATA", ns);
// System.out.println("starting prefix mapping for
prefix " + pr + " for " + ns);
- contentHandler.startPrefixMapping(prefix, ns);
+ contentHandler.startPrefixMapping(pr, ns);
}
}
@@ -487,6 +514,78 @@
}
}
+ /**
+ * Searches the namespace for a given namespace prefix starting from a
+ * given Element.
+ *
+ * <p>Note that this resolves the prefix in the orginal DOM-tree, not in
+ * the [EMAIL PROTECTED] ElementInfo} objects. This is used to resolve
prefixes
+ * of elements or attributes created with createElement or setAttribute
+ * instead of createElementNS or setAttributeNS.
+ *
+ * <p>The code in this method is largely based on
+ * org.apache.xml.utils.DOMHelper.getNamespaceForPrefix() (from Xalan).
+ *
+ * @param prefix the prefix to look for, can be empty or null to find the
+ * default namespace
+ *
+ * @return the namespace, or null if not found.
+ */
+ public String getNamespaceForPrefix(String prefix, Element
namespaceContext) {
+ // TODO cache this information in the ElementInfo objects?
+ int type;
+ Node parent = namespaceContext;
+ String namespace = null;
+
+ if (prefix == null)
+ prefix = "";
+
+ if (prefix.equals("xml")) {
+ namespace = "http://www.w3.org/XML/1998/namespace";
+ } else if(prefix.equals("xmlns")) {
+ namespace = "http://www.w3.org/2000/xmlns/";
+ } else {
+ // Attribute name for this prefix's declaration
+ String declname = (prefix == "") ? "xmlns" : "xmlns:" + prefix;
+
+ // Scan until we run out of Elements or have resolved the namespace
+ while ((null != parent) && (null == namespace)
+ && (((type = parent.getNodeType()) == Node.ELEMENT_NODE)
+ || (type == Node.ENTITY_REFERENCE_NODE))) {
+ if (type == Node.ELEMENT_NODE) {
+ Attr attr=((Element)parent).getAttributeNode(declname);
+ if(attr!=null) {
+ namespace = attr.getNodeValue();
+ break;
+ }
+ }
+
+ parent = parent.getParentNode();
+ }
+ }
+
+ return namespace;
+ }
+
+ /**
+ * Splits a nodeName into a prefix and a localName
+ *
+ * @return an array containing two elements, the first one is the prefix
(can be null), the
+ * second one is the localName
+ */
+ private String[] getPrefixAndLocalName(String nodeName) {
+ String prefix, localName;
+ int colonPos = nodeName.indexOf(":");
+ if (colonPos != -1) {
+ prefix = nodeName.substring(0, colonPos);
+ localName = nodeName.substring(colonPos + 1, nodeName.length());
+ } else {
+ prefix = null;
+ localName = nodeName;
+ }
+ return new String[] {prefix, localName};
+ }
+
/**
* End processing of given node
@@ -535,9 +634,9 @@
public String namespaceURI;
public String qName;
public Map namespaceDeclarations = null;
- public NamespaceNormalizingDOMStreamer.ElementInfo parent;
+ public ElementInfo parent;
- public ElementInfo(NamespaceNormalizingDOMStreamer.ElementInfo parent) {
+ public ElementInfo(ElementInfo parent) {
this.parent = parent;
}
@@ -582,12 +681,11 @@
* Finds a prefix declaration on this element or containing elements.
*/
public String findPrefix(String namespaceURI) {
- if (namespaceDeclarations == null || namespaceDeclarations.size()
== 0)
- return null;
-
- String prefix = getPrefix(namespaceURI);
- if (prefix != null)
- return prefix;
+ if (namespaceDeclarations != null && namespaceDeclarations.size()
!= 0) {
+ String prefix = getPrefix(namespaceURI);
+ if (prefix != null)
+ return prefix;
+ }
if (parent != null)
return parent.findPrefix(namespaceURI);
else
@@ -598,13 +696,12 @@
* Finds a namespace declaration on this element or containing elements.
*/
public String findNamespaceURI(String prefix) {
- if (namespaceDeclarations == null || namespaceDeclarations.size()
== 0)
- return null;
-
- String uri = (String) namespaceDeclarations.get(prefix);
- if (uri != null)
- return uri;
- else if (parent != null)
+ if (namespaceDeclarations != null && namespaceDeclarations.size()
!= 0) {
+ String uri = (String) namespaceDeclarations.get(prefix);
+ if (uri != null)
+ return uri;
+ }
+ if (parent != null)
return parent.findNamespaceURI(prefix);
else
return null;