package com.ctc.wstx.evt;

import java.io.IOException;
import java.io.Writer;
import java.util.*;

import javax.xml.XMLConstants;
import javax.xml.namespace.NamespaceContext;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.stream.events.Namespace;

import com.ctc.wstx.util.BaseNsContext;
import com.ctc.wstx.util.DataUtil;

Hierarchic NamespaceContext implementation used when constructing event and namespace information explicitly via XMLEventFactory, not by a stream reader.

TODO:

  • Figure out a way to check for namespace masking; tricky but not impossible to determine
/** * Hierarchic {@link NamespaceContext} implementation used when constructing * event and namespace information explicitly via * {@link javax.xml.stream.XMLEventFactory}, * not by a stream reader. *<p> * TODO: *<ul> * <li>Figure out a way to check for namespace masking; tricky but not * impossible to determine * </li> *</ul> */
public class MergedNsContext extends BaseNsContext { final NamespaceContext mParentCtxt;
List of Namespace instances.
/** * List of {@link Namespace} instances. */
final List<Namespace> mNamespaces; Map<String,Namespace> mNsByPrefix = null; Map<String,Namespace> mNsByURI = null; protected MergedNsContext(NamespaceContext parentCtxt, List<Namespace> localNs) { mParentCtxt = parentCtxt; if (localNs == null){ mNamespaces = Collections.emptyList(); } else { mNamespaces = localNs; } } public static BaseNsContext construct(NamespaceContext parentCtxt, List<Namespace> localNs) { return new MergedNsContext(parentCtxt, localNs); } /* ///////////////////////////////////////////// // NamespaceContext API ///////////////////////////////////////////// */ @Override public String doGetNamespaceURI(String prefix) { // Note: base class checks for 'known' problems and prefixes: if (mNsByPrefix == null) { mNsByPrefix = buildByPrefixMap(); } Namespace ns = mNsByPrefix.get(prefix); if (ns == null && mParentCtxt != null) { return mParentCtxt.getNamespaceURI(prefix); } return (ns == null) ? null : ns.getNamespaceURI(); } @Override public String doGetPrefix(String nsURI) { // Note: base class checks for 'known' problems and prefixes: if (mNsByURI == null) { mNsByURI = buildByNsURIMap(); } Namespace ns = mNsByURI.get(nsURI); if (ns == null && mParentCtxt != null) { return mParentCtxt.getPrefix(nsURI); } return (ns == null) ? null : ns.getPrefix(); } @Override public Iterator<String> doGetPrefixes(String nsURI) { // Note: base class checks for 'known' problems and prefixes: ArrayList<String> l = null; for (int i = 0, len = mNamespaces.size(); i < len; ++i) { Namespace ns = mNamespaces.get(i); String uri = ns.getNamespaceURI(); if (uri == null) { uri = ""; } if (uri.equals(nsURI)) { if (l == null) { l = new ArrayList<String>(); } String prefix = ns.getPrefix(); l.add((prefix == null) ? "" : prefix); } } if (mParentCtxt != null) { @SuppressWarnings("unchecked") Iterator<String> it = /*(Iterator<String>)*/mParentCtxt.getPrefixes(nsURI); if (l == null) { return it; } while (it.hasNext()) { l.add(it.next()); } } if (l == null) { return DataUtil.emptyIterator(); } return l.iterator(); } /* ///////////////////////////////////////////// // Extended API ///////////////////////////////////////////// */
Method that returns information about namespace definition declared in this scope; not including ones declared in outer scopes.
/** * Method that returns information about namespace definition declared * in this scope; not including ones declared in outer scopes. */
@Override public Iterator<Namespace> getNamespaces() { return mNamespaces.iterator(); } @Override public void outputNamespaceDeclarations(Writer w) throws IOException { for (int i = 0, len = mNamespaces.size(); i < len; ++i) { Namespace ns = mNamespaces.get(i); w.write(' '); w.write(XMLConstants.XMLNS_ATTRIBUTE); if (!ns.isDefaultNamespaceDeclaration()) { w.write(':'); w.write(ns.getPrefix()); } w.write("=\""); w.write(ns.getNamespaceURI()); w.write('"'); } }
Method called by the matching start element class to output all namespace declarations active in current namespace scope, if any.
/** * Method called by the matching start element class to * output all namespace declarations active in current namespace * scope, if any. */
@Override public void outputNamespaceDeclarations(XMLStreamWriter w) throws XMLStreamException { for (int i = 0, len = mNamespaces.size(); i < len; ++i) { Namespace ns = mNamespaces.get(i); if (ns.isDefaultNamespaceDeclaration()) { w.writeDefaultNamespace(ns.getNamespaceURI()); } else { w.writeNamespace(ns.getPrefix(), ns.getNamespaceURI()); } } } /* ///////////////////////////////////////////// // Private methods: ///////////////////////////////////////////// */ private Map<String,Namespace> buildByPrefixMap() { int len = mNamespaces.size(); if (len == 0) { return Collections.emptyMap(); } LinkedHashMap<String,Namespace> m = new LinkedHashMap<String,Namespace>(1 + len + (len>>1)); for (int i = 0; i < len; ++i) { Namespace ns = mNamespaces.get(i); String prefix = ns.getPrefix(); if (prefix == null) { // shouldn't happen but... prefix = ""; } m.put(prefix, ns); } return m; } private Map<String,Namespace> buildByNsURIMap() { int len = mNamespaces.size(); if (len == 0) { return Collections.emptyMap(); } LinkedHashMap<String,Namespace> m = new LinkedHashMap<String,Namespace>(1 + len + (len>>1)); for (int i = 0; i < len; ++i) { Namespace ns = mNamespaces.get(i); String uri = ns.getNamespaceURI(); if (uri == null) { // shouldn't happen but... uri = ""; } m.put(uri, ns); } return m; } }