namespacemappings.java

来自「JAVA 所有包」· Java 代码 · 共 326 行

JAVA
326
字号
/* * Copyright 2003-2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *//* * $Id: NamespaceMappings.java,v 1.2.4.1 2005/09/15 08:15:19 suresh_emailid Exp $ */package com.sun.org.apache.xml.internal.serializer;import java.util.Enumeration;import java.util.Hashtable;import java.util.Stack;import org.xml.sax.ContentHandler;import org.xml.sax.SAXException;/** * This class keeps track of the currently defined namespaces. Conceptually the * prefix/uri/depth triplets are pushed on a stack pushed on a stack. The depth * indicates the nesting depth of the element for which the mapping was made. *  * <p>For example: * <pre> * <chapter xmlns:p1="def"> *   <paragraph xmlns:p2="ghi"> *      <sentance xmlns:p3="jkl"> *      </sentance> *    </paragraph> *    <paragraph xlmns:p4="mno"> *    </paragraph> * </chapter> * </pre> *  * When the <chapter> element is encounted the prefix "p1" associated with uri * "def" is pushed on the stack with depth 1. * When the first <paragraph> is encountered "p2" and "ghi" are pushed with * depth 2. * When the <sentance> is encountered "p3" and "jkl" are pushed with depth 3. * When </sentance> occurs the popNamespaces(3) will pop "p3"/"jkl" off the * stack.  Of course popNamespaces(2) would pop anything with depth 2 or * greater. *  * So prefix/uri pairs are pushed and poped off the stack as elements are * processed.  At any given moment of processing the currently visible prefixes * are on the stack and a prefix can be found given a uri, or a uri can be found * given a prefix. *  * This class is public only because it is used by Xalan. It is not a public API *  * @xsl.usage internal */public class NamespaceMappings{    /**     * This member is continually incremented when new prefixes need to be     * generated. ("ns0"  "ns1" ...)     */    private int count = 0;    /**     * Each entry (prefix) in this hashtable points to a Stack of URIs     * This table maps a prefix (String) to a Stack of prefix mappings.     * All mappings in that retrieved stack have the same prefix,     * though possibly different URI's or depths. Such a stack must have     * mappings at deeper depths push later on such a stack.  Mappings pushed     * earlier on the stack will have smaller values for MappingRecord.m_declarationDepth.     */    private Hashtable m_namespaces = new Hashtable();    /**      * The top of this stack contains the MapRecord     * of the last declared a namespace.     * Used to know how many prefix mappings to pop when leaving     * the current element depth.     * For every prefix mapping the current element depth is      * pushed on this stack.     * That way all prefixes pushed at the current depth can be      * removed at the same time.     * Used to ensure prefix/uri map scopes are closed correctly     *     */    private Stack m_nodeStack = new Stack();    private static final String EMPTYSTRING = "";    private static final String XML_PREFIX = "xml"; // was "xmlns"    /**     * Default constructor     * @see java.lang.Object#Object()     */    public NamespaceMappings()    {        initNamespaces();    }    /**     * This method initializes the namespace object with appropriate stacks     * and predefines a few prefix/uri pairs which always exist.     */    private void initNamespaces()    {         // Define the default namespace (initially maps to "" uri)        Stack stack;        m_namespaces.put(EMPTYSTRING, stack = new Stack());        stack.push(new MappingRecord(EMPTYSTRING,EMPTYSTRING,0));        m_namespaces.put(XML_PREFIX, stack = new Stack());        stack.push(new MappingRecord( XML_PREFIX,            "http://www.w3.org/XML/1998/namespace",0));        m_nodeStack.push(new MappingRecord(null,null,-1));    }    /**     * Use a namespace prefix to lookup a namespace URI.     *      * @param prefix String the prefix of the namespace     * @return the URI corresponding to the prefix     */    public String lookupNamespace(String prefix)    {        final Stack stack = (Stack) m_namespaces.get(prefix);        return stack != null && !stack.isEmpty() ?             ((MappingRecord) stack.peek()).m_uri : null;    }        MappingRecord getMappingFromPrefix(String prefix) {        final Stack stack = (Stack) m_namespaces.get(prefix);        return stack != null && !stack.isEmpty() ?             ((MappingRecord) stack.peek()) : null;    }    /**     * Given a namespace uri, and the namespaces mappings for the      * current element, return the current prefix for that uri.     *      * @param uri the namespace URI to be search for     * @return an existing prefix that maps to the given URI, null if no prefix     * maps to the given namespace URI.     */    public String lookupPrefix(String uri)    {        String foundPrefix = null;        Enumeration prefixes = m_namespaces.keys();        while (prefixes.hasMoreElements())        {            String prefix = (String) prefixes.nextElement();            String uri2 = lookupNamespace(prefix);            if (uri2 != null && uri2.equals(uri))            {                foundPrefix = prefix;                break;            }        }        return foundPrefix;    }        MappingRecord getMappingFromURI(String uri)    {        MappingRecord foundMap = null;        Enumeration prefixes = m_namespaces.keys();        while (prefixes.hasMoreElements())        {            String prefix = (String) prefixes.nextElement();            MappingRecord map2 = getMappingFromPrefix(prefix);            if (map2 != null && (map2.m_uri).equals(uri))            {                foundMap = map2;                break;            }        }        return foundMap;    }    /**     * Undeclare the namespace that is currently pointed to by a given prefix     */    boolean popNamespace(String prefix)    {        // Prefixes "xml" and "xmlns" cannot be redefined        if (prefix.startsWith(XML_PREFIX))        {            return false;        }        Stack stack;        if ((stack = (Stack) m_namespaces.get(prefix)) != null)        {            stack.pop();            return true;        }        return false;    }    /**     * Declare a mapping of a prefix to namespace URI at the given element depth.     * @param prefix a String with the prefix for a qualified name     * @param uri a String with the uri to which the prefix is to map     * @param elemDepth the depth of current declaration     */    boolean pushNamespace(String prefix, String uri, int elemDepth)    {        // Prefixes "xml" and "xmlns" cannot be redefined        if (prefix.startsWith(XML_PREFIX))        {            return false;        }        Stack stack;        // Get the stack that contains URIs for the specified prefix        if ((stack = (Stack) m_namespaces.get(prefix)) == null)        {            m_namespaces.put(prefix, stack = new Stack());        }        if (!stack.empty() && uri.equals(((MappingRecord)stack.peek()).m_uri))        {            return false;        }        MappingRecord map = new MappingRecord(prefix,uri,elemDepth);        stack.push(map);        m_nodeStack.push(map);        return true;    }    /**     * Pop, or undeclare all namespace definitions that are currently     * declared at the given element depth, or deepter.     * @param elemDepth the element depth for which mappings declared at this     * depth or deeper will no longer be valid     * @param saxHandler The ContentHandler to notify of any endPrefixMapping()     * calls.  This parameter can be null.     */    void popNamespaces(int elemDepth, ContentHandler saxHandler)    {        while (true)        {            if (m_nodeStack.isEmpty())                return;            MappingRecord map = (MappingRecord)(m_nodeStack.peek());            int depth = map.m_declarationDepth;            if (depth < elemDepth)                return;            /* the depth of the declared mapping is elemDepth or deeper             * so get rid of it             */            map = (MappingRecord) m_nodeStack.pop();            final String prefix = map.m_prefix;             popNamespace(prefix);            if (saxHandler != null)            {                try                {                    saxHandler.endPrefixMapping(prefix);                }                catch (SAXException e)                {                    // not much we can do if they aren't willing to listen                }            }                       }    }    /**     * Generate a new namespace prefix ( ns0, ns1 ...) not used before     * @return String a new namespace prefix ( ns0, ns1, ns2 ...)     */    public String generateNextPrefix()    {        return "ns" + (count++);    }     /**     * This method makes a clone of this object.     *     */    public Object clone() throws CloneNotSupportedException {        NamespaceMappings clone = new NamespaceMappings();        clone.m_nodeStack = (Stack) m_nodeStack.clone();        clone.m_namespaces = (Hashtable) m_namespaces.clone();                clone.count = count;        return clone;            }        final void reset()    {        this.count = 0;        this.m_namespaces.clear();        this.m_nodeStack.clear();                initNamespaces();    }        class MappingRecord {        final String m_prefix;  // the prefix        final String m_uri;     // the uri        // the depth of the element where declartion was made        final int m_declarationDepth;        MappingRecord(String prefix, String uri, int depth) {            m_prefix = prefix;            m_uri = uri;            m_declarationDepth = depth;                    }    }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?