By default namespace declaration attributes such as
xmlns="http://ns.cafeconleche.org/Orders/"
and
xmlns:xlink="http://www.w3.org/1999/xlink"
are not included in the list of
attributes passed to startElement()
.
Instead each such namespace declaration attribute is
signaled
by a call to startPrefixMapping()
immediately before the startElement()
call
corresponding to the start tag of the element where the declaration
appears. Furthermore, the endElement()
call corresponding to the end tag of that element is immediately followed
by an endPrefixMapping()
call.
public void startPrefixMapping(String prefix, String uri) throws SAXException
public void endPrefixMapping(String prefix) throws SAXException
Most of the time you can ignore these events. As long as you only care about
URIs and prefixes on element and attribute names, then
there’s really no need to pay attention to these methods.
You simply inspect
the URIs and prefixes passed in the arguments to the
startElement()
method.
However, in a few applications, including XSLT and schemas, prefixes appear in attribute values and even element content. If so, you need to keep track of which URIs particular prefixes are bound to where.
Keep the prefixes and URIs on a per-document
stack. startPrefixMapping()
pushes the pair onto the stack.
endPrefixMapping()
pops them off.
If at any time while parsing you need to know
the current binding of a prefix you’ve encountered, simply
search down the stack starting with the top. The first
binding you encounter for the prefix is the one you want.
org.xml.sax.helpers.NamespaceSupport
implements this logic.
package org.xml.sax.helpers;
public class NamespaceSupport {
public final static String XMLNS
= "http://www.w3.org/XML/1998/namespace";
public NamespaceSupport();
public void reset();
public void pushContext();
public void popContext();
public boolean declarePrefix(String prefix, String uri);
public String[] processName(String qualifedName,
String parts[], boolean isAttribute);
public String getURI(String prefix);
public Enumeration getPrefixes();
public String getPrefix(String uri);
public Enumeration getPrefixes(String uri);
public Enumeration getDeclaredPrefixes();
}
Call
pushContext()
in the first
startPrefixMapping()
event
before each startElement()
,
declarePrefix()
every
startPrefixMapping()
event,
and
popContext()
in the first
endPrefixMapping()
event
after each endElement()
event.
Add namespace declarations to a context by passing their
prefix and URI as strings to
declarePrefix()
inside each
startPrefixMapping()
call.
Use the empty string
as the prefix to declare the default namespace:
private NamespaceSupport namespaces;
private boolean needNewContext = true;
public void startDocument() {
namespaces = new NamespaceSupport();
}
public void startPrefixMapping(String prefix, String uri)
throws SAXException {
if (needNewContext) {
namespaces.pushContext();
needNewContext = false;
}
namespaces.declarePrefix(prefix, uri);
}
public void endPrefixMapping(String prefix)
throws SAXException {
if (!needNewContext) {
namespaces.popContext();
needNewContext = true;
}
}
The getDeclaredPrefixes()
,
getPrefix()
,
getPrefixes()
,
and getURI()
methods all return
various information about the namespaces in scope in the
current context. For example, this startElement()
method
prints the namespace URI for the values of
type attributes, such as might be found in a schema:
public void startElement(String namespaceURI, String localName,
String qualifiedName, Attributes atts) throws SAXException {
String value = atts.getValue("type");
if (value != null) {
String prefix = "";
if (value.indexOf(':') >= 0) {
prefix = value.substring(0, value.indexOf(':'));
}
String uri = namespaces.getURI(prefix);
}
}
To reuse a
NamespaceSupport
for a new document,
call reset()
, probably from the
startDocument()
method.