14c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson/*
24c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * Licensed to the Apache Software Foundation (ASF) under one
34c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * or more contributor license agreements. See the NOTICE file
44c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * distributed with this work for additional information
54c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * regarding copyright ownership. The ASF licenses this file
64c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * to you under the Apache License, Version 2.0 (the  "License");
74c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * you may not use this file except in compliance with the License.
84c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * You may obtain a copy of the License at
94c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson *
104c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson *     http://www.apache.org/licenses/LICENSE-2.0
114c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson *
124c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * Unless required by applicable law or agreed to in writing, software
134c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS,
144c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
154c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * See the License for the specific language governing permissions and
164c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * limitations under the License.
174c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */
184c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson/*
194c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * $Id: PrefixResolverDefault.java 468655 2006-10-28 07:12:06Z minchau $
204c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */
214c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonpackage org.apache.xml.utils;
224c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
234c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.w3c.dom.NamedNodeMap;
244c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.w3c.dom.Node;
254c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
264c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson/**
274c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * This class implements a generic PrefixResolver that
284c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * can be used to perform prefix-to-namespace lookup
294c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * for the XPath object.
304c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @xsl.usage general
314c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */
324c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonpublic class PrefixResolverDefault implements PrefixResolver
334c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson{
344c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
354c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
364c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * The context to resolve the prefix from, if the context
374c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * is not given.
384c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
394c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  Node m_context;
404c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
414c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
424c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Construct a PrefixResolverDefault object.
434c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param xpathExpressionContext The context from
444c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * which XPath expression prefixes will be resolved.
454c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Warning: This will not work correctly if xpathExpressionContext
464c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * is an attribute node.
474c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
484c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public PrefixResolverDefault(Node xpathExpressionContext)
494c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
504c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_context = xpathExpressionContext;
514c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
524c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
534c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
544c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Given a namespace, get the corrisponding prefix.  This assumes that
554c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * the PrevixResolver hold's it's own namespace context, or is a namespace
564c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * context itself.
574c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param prefix Prefix to resolve.
584c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return Namespace that prefix resolves to, or null if prefix
594c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * is not bound.
604c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
614c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public String getNamespaceForPrefix(String prefix)
624c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
634c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return getNamespaceForPrefix(prefix, m_context);
644c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
654c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
664c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
674c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Given a namespace, get the corrisponding prefix.
684c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Warning: This will not work correctly if namespaceContext
694c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * is an attribute node.
704c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param prefix Prefix to resolve.
714c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param namespaceContext Node from which to start searching for a
724c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * xmlns attribute that binds a prefix to a namespace.
734c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return Namespace that prefix resolves to, or null if prefix
744c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * is not bound.
754c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
764c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public String getNamespaceForPrefix(String prefix,
774c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                                      org.w3c.dom.Node namespaceContext)
784c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
794c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
804c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    Node parent = namespaceContext;
814c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    String namespace = null;
824c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
834c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    if (prefix.equals("xml"))
844c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    {
854c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      namespace = Constants.S_XMLNAMESPACEURI;
864c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
874c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    else
884c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    {
894c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      int type;
904c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
914c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      while ((null != parent) && (null == namespace)
924c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson             && (((type = parent.getNodeType()) == Node.ELEMENT_NODE)
934c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                 || (type == Node.ENTITY_REFERENCE_NODE)))
944c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      {
954c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        if (type == Node.ELEMENT_NODE)
964c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        {
974c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                if (parent.getNodeName().indexOf(prefix+":") == 0)
984c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                        return parent.getNamespaceURI();
994c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          NamedNodeMap nnm = parent.getAttributes();
1004c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1014c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          for (int i = 0; i < nnm.getLength(); i++)
1024c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          {
1034c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            Node attr = nnm.item(i);
1044c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            String aname = attr.getNodeName();
1054c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            boolean isPrefix = aname.startsWith("xmlns:");
1064c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1074c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            if (isPrefix || aname.equals("xmlns"))
1084c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            {
1094c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson              int index = aname.indexOf(':');
1104c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson              String p = isPrefix ? aname.substring(index + 1) : "";
1114c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1124c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson              if (p.equals(prefix))
1134c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson              {
1144c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                namespace = attr.getNodeValue();
1154c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1164c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                break;
1174c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson              }
1184c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            }
1194c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          }
1204c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        }
1214c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1224c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        parent = parent.getParentNode();
1234c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      }
1244c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
1254c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1264c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return namespace;
1274c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
1284c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1294c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
1304c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Return the base identifier.
1314c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
1324c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return null
1334c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
1344c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public String getBaseIdentifier()
1354c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
1364c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return null;
1374c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
1384c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	/**
1394c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	 * @see PrefixResolver#handlesNullPrefixes()
1404c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	 */
1414c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	public boolean handlesNullPrefixes() {
1424c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson		return false;
1434c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	}
1444c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1454c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson}
146