001: /* Copyright 2005 Elliotte Rusty Harold
002:
003: This library is free software; you can redistribute it and/or modify
004: it under the terms of version 2.1 of the GNU Lesser General Public
005: License as published by the Free Software Foundation.
006:
007: This library is distributed in the hope that it will be useful,
008: but WITHOUT ANY WARRANTY; without even the implied warranty of
009: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
010: GNU Lesser General Public License for more details.
011:
012: You should have received a copy of the GNU Lesser General Public
013: License along with this library; if not, write to the
014: Free Software Foundation, Inc., 59 Temple Place, Suite 330,
015: Boston, MA 02111-1307 USA
016:
017: You can contact Elliotte Rusty Harold by sending e-mail to
018: elharo@metalab.unc.edu. Please include the word "XOM" in the
019: subject line. The XOM home page is located at http://www.xom.nu/
020: */
021:
022: package nu.xom;
023:
024: /**
025: * <p>
026: * Represents a namespace in scope. It is used by XOM's
027: * XPath implementation for the namespace axis. However, it is not
028: * really part of the XOM data model. Namespace objects are only
029: * created as needed when evaluating XPath. While a namespace node has
030: * a parent element (which may be null), that element does not know
031: * about these namespace nodes and cannot remove them. (This is an
032: * inconsistency in the XPath data model, and is shared with attributes
033: * which also have parents but are not children.)
034: * </p>
035: *
036: * @author Elliotte Rusty Harold
037: * @version 1.1b3
038: *
039: */
040: public final class Namespace extends Node {
041:
042: private final String prefix;
043: private final String uri;
044:
045: /**
046: * Namespace URI specified for <code>xml</code> prefix
047: */
048: public final static String XML_NAMESPACE = "http://www.w3.org/XML/1998/namespace";
049:
050: /**
051: * <p>
052: * Create a new namespace node.
053: * </p>
054: *
055: * @param prefix the prefix for the namespace; may be the empty
056: * string or a non-colonized name
057: * @param URI the namespace URI
058: * @param parent the element that possesses this namespace node
059: *
060: * @throws MalformedURIException if <code>URI</code> is
061: * not an RFC 3986 URI reference
062: * @throws IllegalNameException if
063: * <ul>
064: * <li>The prefix is <code>xmlns</code>.</li>
065: * <li>The prefix is not the empty string, and the URI is
066: * null or the empty string.</li>
067: * </ul>
068: * @throws NamespaceConflictException if
069: * <ul>
070: * <li>The prefix is the empty string, and the URI is
071: * null or the empty string.</li>
072: * <li>The prefix is <code>xml</code>, and the URI is not
073: * <code>http://www.w3.org/XML/1998/namespace</code>.</li>
074: * <li>The prefix is not <code>xml</code>, and the URI is
075: * <code>http://www.w3.org/XML/1998/namespace</code>.</li>
076: * </ul>
077: */
078: public Namespace(String prefix, String URI, Element parent) {
079:
080: if (prefix == null)
081: prefix = "";
082: else if ("xmlns".equals(prefix)) {
083: throw new IllegalNameException(
084: "The xmlns prefix may not be bound to a URI.");
085: } else if ("xml".equals(prefix)) {
086: if (!XML_NAMESPACE.equals(URI)) {
087: throw new NamespaceConflictException(
088: "The prefix xml can only be bound to the URI "
089: + "http://www.w3.org/XML/1998/namespace");
090: }
091: }
092:
093: if (prefix.length() != 0)
094: Verifier.checkNCName(prefix);
095:
096: if (URI == null)
097: URI = "";
098: else if (URI.equals(XML_NAMESPACE)) {
099: if (!"xml".equals(prefix)) {
100: throw new NamespaceConflictException(
101: "The URI http://www.w3.org/XML/1998/namespace can "
102: + "only be bound to the prefix xml");
103: }
104: }
105:
106: if (URI.length() == 0) { // faster than "".equals(uri)
107: if (prefix.length() != 0) {
108: throw new NamespaceConflictException(
109: "Prefixed elements must have namespace URIs.");
110: }
111: } else
112: Verifier.checkAbsoluteURIReference(URI);
113:
114: this .prefix = prefix;
115: this .uri = URI;
116: super .setParent(parent);
117: }
118:
119: /**
120: * <p>
121: * Returns the namespace prefix, or the empty string if this node
122: * is the default namespace.
123: * </p>
124: *
125: * @return the namespace prefix
126: */
127: public String getPrefix() {
128: return prefix;
129: }
130:
131: /**
132: * <p>
133: * Returns the namespace URI.
134: * </p>
135: *
136: * @return the namespace URI
137: */
138: public String getValue() {
139: return uri;
140: }
141:
142: /**
143: * <p>
144: * Throws <code>IndexOutOfBoundsException</code> because
145: * namespaces do not have children.
146: * </p>
147: *
148: * @return never returns because document type declarations do not
149: * have children. Always throws an exception.
150: *
151: * @param position the index of the child node to return
152: *
153: * @throws IndexOutOfBoundsException because document type declarations
154: * do not have children
155: */
156: public Node getChild(int position) {
157: throw new IndexOutOfBoundsException(
158: "Namespaces do not have children");
159: }
160:
161: /**
162: * <p>
163: * Returns 0 because namespaces do not have
164: * children.
165: * </p>
166: *
167: * @return zero
168: */
169: public int getChildCount() {
170: return 0;
171: }
172:
173: /**
174: * <p>
175: * Returns a copy of this namespace which has
176: * the same prefix and URI, but no parent.
177: * </p>
178: *
179: * @return a copy of this <code>Namespace</code>
180: * that is not part of a document
181: */
182: public Node copy() {
183: return new Namespace(prefix, uri, null);
184: }
185:
186: /**
187: * <p>
188: * Removes this namespace node from its parent.
189: * </p>
190: *
191: * @see nu.xom.Node#detach()
192: */
193: public void detach() {
194: super .setParent(null);
195: }
196:
197: /**
198: * <p>
199: * Returns a string containing the actual XML
200: * form of the namespace declaration represented
201: * by this object. For example,
202: * <code>xmlns:pre="http://www.example.org/"</code>.
203: * </p>
204: *
205: * @return a <code>String</code> containing
206: * an XML namespace declaration
207: */
208: public String toXML() {
209: String colon = prefix.equals("") ? "" : ":";
210: return "xmlns" + colon + prefix + "=\"" + uri + "\"";
211: }
212:
213: /**
214: * <p>
215: * Returns a string form of the
216: * <code>Namespace</code> suitable for debugging
217: * and diagnosis. It deliberately does not return
218: * an actual XML namespace declaration.
219: * </p>
220: *
221: * @return a string representation of this object
222: */
223: public String toString() {
224: return "[Namespace: " + this .toXML() + "]";
225: }
226:
227: }
|