/* * The contents of this file are subject to the terms * of the Common Development and Distribution License * (the "License"). You may not use this file except * in compliance with the License. * * You can obtain a copy of the license at * https://jaxp.dev.java.net/CDDLv1.0.html. * See the License for the specific language governing * permissions and limitations under the License. * * When distributing Covered Code, include this CDDL * HEADER in each file and include the License file at * https://jaxp.dev.java.net/CDDLv1.0.html * If applicable add the following below this CDDL HEADER * with the fields enclosed by brackets "[]" replaced with * your own identifying information: Portions Copyright * [year] [name of copyright owner] */ /* * $Id: NamespaceContextHelper.java,v 1.2 2006-03-28 20:54:02 ndw Exp $ * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. * Portions Copyright 2010 Thomas 'PointedEars' Lahn */ package com.nwalsh.namespace; import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; import javax.xml.namespace.NamespaceContext; /* * NOTE: Skip XML 1.1 validity tests because we don't want to recompile * org.apache.xerces for Android -- PointedEars */ // import org.apache.xerces.util.XML11Char; /** * Helper implementation of the javax.xml.namespace.NamespaceContext interface. * *
* This class implements the JAXP (1.3+) * {@link javax.xml.namespace.NamespaceContext} interface. This is the interface * used by the JAXP XPath APIs to establish namespace bindings for XPath * expressions. *
* *
* There are two errors (in retrospect) with respect to the namespace context in
* the XPath API. First, there's no way to construct a new one. Given an XPath
* you can find out what context it is using, but if you want to construct a new
* expression, there's no standard class that you can instantiate to build a new
* context. Second, the {@link javax.xml.namespace.NamespaceContext} interface
* is obviously (again, in retrospect) missing a method that returns an iterator
* that will allow you to find
* This class addresses the first error by providing an object that you can
* instantiate that implements the {@link javax.xml.namespace.NamespaceContext}
* interface. It's not a
* There's really no way to address the second error. An interface, like * {@link javax.xml.namespace.NamespaceContext}, is immutable once released into * the wild in the Java platform. (This is a consequence of backwards * compatibility rules.) To really address the problem, we'll have to invent a * new interface or provide an alternative abstract class that implementations * will be required to use, or something. However, as an experiment, this class * implements a couple of extra methods that we might wish had been in the * interface. These methods are carefully identified as non-standard. Having * them here really isn't all that useful because your underlying XPath * implementation isn't likely to return instances of this class. *
* ** There are three ways to instantiate this class: *
* ** After the object has been instantiated, you can call the * {@link #add(String,String)} method to add additional bindings to the * namespace context. Because I'm not sure how and where the XPath API * implementations might save pointers to the context object, I've imposed a * number of rules designed to make sure that the context remains coherent: *
* ** Even with these rules, you can't assume that the context is thread safe. * Don't allow it to be changed while someone else is reading it. *
* ** Other notes: *
* *getNamespaceURIs(String prefix)
method because
* there can be at most one URI bound to any given prefix. Wrapping an interator
* around the mapping available with {@link #getNamespaceURI(String)} seemed
* silly.* Creates an empty namespace context. *
*/ public NamespaceContextHelper() { } /** * Creates a new instance of NamespaceContextHelper. * *
* Creates a namespace context with the bindings specified in
* initialNamespaces
.
*
* Creates a namespace context with the specified prefix
bound to
* uri
.
*
prefix
or uri
is
* null
.
* @throws IllegalArgumentException
* if the caller attempts to change the binding of
* prefix
, if the caller attempts to bind the prefix "
* xml
"
* or the namespace "
* http://www.w3.org/XML/1998/namespace
" incorrectly,
* if the caller attempts to bind the prefix "xmlns
" or
* the namespace
* "http://www.w3.org/2000/xmlns
", or if the
* prefix
is
* not a valid NCName.
*/
public void add(String prefix, String uri)
{
if (prefix == null || uri == null)
{
throw new NullPointerException(
"Null prefix or uri passed to NamespaceContextHelper");
}
if (this.ns.containsKey(prefix))
{
String curURI = this.ns.get(prefix);
if (uri.equals(curURI))
{
return;
}
throw new IllegalArgumentException(
"Attempt to change binding in NamespaceContextHelper");
}
if ("xml".equals(prefix)
&& !"http://www.w3.org/XML/1998/namespace".equals(uri))
{
throw new IllegalArgumentException(
"The prefix 'xml' can only be bound to 'http://www.w3.org/XML/1998/namespace' in NamespaceContextHelper");
}
if ("http://www.w3.org/XML/1998/namespace".equals(uri)
&& !"xml".equals(prefix))
{
throw new IllegalArgumentException(
"The namespace 'http://www.w3.org/XML/1998/namespace' can only have the prefix 'xml' in NamespaceContextHelper");
}
if ("xmlns".equals(prefix)
|| "http://www.w3.org/2000/xmlns".equals(uri))
{
throw new IllegalArgumentException(
"Neither the prefix 'xmlns' nor the URI 'http://www.w3.org/2000/xmlns' can be bound in NamespaceContextHelper");
}
if ("".equals(prefix))
{
this.ns.put(prefix, uri);
}
else
{
/*
* NOTE: Skip XML 1.1 validity tests because we don't want to recompile
* org.apache.xerces for Android -- PointedEars
*/
// if (XML11Char.isXML11ValidNCName (prefix)) {
this.ns.put(prefix, uri);
// } else {
// throw new IllegalArgumentException
// ("Prefix is not a valid NCName in NamespaceContextHelper");
// }
}
}
/** Implements the NamespaceContext getNamespaceURI method. */
public String getNamespaceURI(String prefix)
{
return this.ns.get(prefix);
}
/** Implements the NamespaceContext getPrefix method. */
public String getPrefix(String namespaceURI)
{
if (this.ns.containsValue(namespaceURI))
{
Enumeration* Returns an iterator over all of the prefixes in the namespace context. Note * that multiple prefixes may be bound to the same URI. *
*/ public Iterator getPrefixes() { return this.getPrefixes(null); } /** Implements the NamespaceContext getPrefixes method. */ public Iterator getPrefixes(String namespaceURI) { return new NSIterator(this.ns, namespaceURI); } /** * Implements a* Returns an iterator over all of the namespace URIs in the namespace * context. Note that each namespace URI is returned exactly once, even if it * is bound to several different prefixes. *
*/ public Iterator getNamespaceURIs() { // Make sure each URI is returned at most once... Hashtable