2
* Licensed to the Apache Software Foundation (ASF) under one
3
* or more contributor license agreements. See the NOTICE file
4
* distributed with this work for additional information
5
* regarding copyright ownership. The ASF licenses this file
6
* to you under the Apache License, Version 2.0 (the "License");
7
* you may not use this file except in compliance with the License.
8
* You may obtain a copy of the License at
10
* http://www.apache.org/licenses/LICENSE-2.0
12
* Unless required by applicable law or agreed to in writing, software
13
* distributed under the License is distributed on an "AS IS" BASIS,
14
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
* See the License for the specific language governing permissions and
16
* limitations under the License.
19
* $Id: QName.java,v 1.2 2009/12/10 03:18:23 matthewoliver Exp $
21
package org.apache.xml.utils;
23
import java.util.Stack;
24
import java.util.StringTokenizer;
26
import org.apache.xml.res.XMLErrorResources;
27
import org.apache.xml.res.XMLMessages;
29
import org.w3c.dom.Element;
32
* Class to represent a qualified name: "The name of an internal XSLT object,
33
* specifically a named template (see [7 Named Templates]), a mode (see [6.7 Modes]),
34
* an attribute set (see [8.1.4 Named Attribute Sets]), a key (see [14.2 Keys]),
35
* a locale (see [14.3 Number Formatting]), a variable or a parameter (see
36
* [12 Variables and Parameters]) is specified as a QName. If it has a prefix,
37
* then the prefix is expanded into a URI reference using the namespace declarations
38
* in effect on the attribute in which the name occurs. The expanded name
39
* consisting of the local part of the name and the possibly null URI reference
40
* is used as the name of the object. The default namespace is not used for
44
public class QName implements java.io.Serializable
46
static final long serialVersionUID = 467434581652829920L;
52
protected String _localName;
58
protected String _namespaceURI;
61
* The namespace prefix.
64
protected String _prefix;
69
public static final String S_XMLNAMESPACEURI =
70
"http://www.w3.org/XML/1998/namespace";
73
* The cached hashcode, which is calculated at construction time.
76
private int m_hashCode;
79
* Constructs an empty QName.
80
* 20001019: Try making this public, to support Serializable? -- JKESS
85
* Constructs a new QName with the specified namespace URI and
88
* @param namespaceURI The namespace URI if known, or null
89
* @param localName The local name
91
public QName(String namespaceURI, String localName)
93
this(namespaceURI, localName, false);
97
* Constructs a new QName with the specified namespace URI and
100
* @param namespaceURI The namespace URI if known, or null
101
* @param localName The local name
102
* @param validate If true the new QName will be validated and an IllegalArgumentException will
103
* be thrown if it is invalid.
105
public QName(String namespaceURI, String localName, boolean validate)
108
// This check was already here. So, for now, I will not add it to the validation
109
// that is done when the validate parameter is true.
110
if (localName == null)
111
throw new IllegalArgumentException(XMLMessages.createXMLMessage(
112
XMLErrorResources.ER_ARG_LOCALNAME_NULL, null)); //"Argument 'localName' is null");
116
if (!XML11Char.isXML11ValidNCName(localName))
118
throw new IllegalArgumentException(XMLMessages.createXMLMessage(
119
XMLErrorResources.ER_ARG_LOCALNAME_INVALID,null )); //"Argument 'localName' not a valid NCName");
123
_namespaceURI = namespaceURI;
124
_localName = localName;
125
m_hashCode = toString().hashCode();
129
* Constructs a new QName with the specified namespace URI, prefix
132
* @param namespaceURI The namespace URI if known, or null
133
* @param prefix The namespace prefix is known, or null
134
* @param localName The local name
137
public QName(String namespaceURI, String prefix, String localName)
139
this(namespaceURI, prefix, localName, false);
143
* Constructs a new QName with the specified namespace URI, prefix
146
* @param namespaceURI The namespace URI if known, or null
147
* @param prefix The namespace prefix is known, or null
148
* @param localName The local name
149
* @param validate If true the new QName will be validated and an IllegalArgumentException will
150
* be thrown if it is invalid.
152
public QName(String namespaceURI, String prefix, String localName, boolean validate)
155
// This check was already here. So, for now, I will not add it to the validation
156
// that is done when the validate parameter is true.
157
if (localName == null)
158
throw new IllegalArgumentException(XMLMessages.createXMLMessage(
159
XMLErrorResources.ER_ARG_LOCALNAME_NULL, null)); //"Argument 'localName' is null");
163
if (!XML11Char.isXML11ValidNCName(localName))
165
throw new IllegalArgumentException(XMLMessages.createXMLMessage(
166
XMLErrorResources.ER_ARG_LOCALNAME_INVALID,null )); //"Argument 'localName' not a valid NCName");
169
if ((null != prefix) && (!XML11Char.isXML11ValidNCName(prefix)))
171
throw new IllegalArgumentException(XMLMessages.createXMLMessage(
172
XMLErrorResources.ER_ARG_PREFIX_INVALID,null )); //"Argument 'prefix' not a valid NCName");
176
_namespaceURI = namespaceURI;
178
_localName = localName;
179
m_hashCode = toString().hashCode();
183
* Construct a QName from a string, without namespace resolution. Good
184
* for a few odd cases.
186
* @param localName Local part of qualified name
189
public QName(String localName)
191
this(localName, false);
195
* Construct a QName from a string, without namespace resolution. Good
196
* for a few odd cases.
198
* @param localName Local part of qualified name
199
* @param validate If true the new QName will be validated and an IllegalArgumentException will
200
* be thrown if it is invalid.
202
public QName(String localName, boolean validate)
205
// This check was already here. So, for now, I will not add it to the validation
206
// that is done when the validate parameter is true.
207
if (localName == null)
208
throw new IllegalArgumentException(XMLMessages.createXMLMessage(
209
XMLErrorResources.ER_ARG_LOCALNAME_NULL, null)); //"Argument 'localName' is null");
213
if (!XML11Char.isXML11ValidNCName(localName))
215
throw new IllegalArgumentException(XMLMessages.createXMLMessage(
216
XMLErrorResources.ER_ARG_LOCALNAME_INVALID,null )); //"Argument 'localName' not a valid NCName");
219
_namespaceURI = null;
220
_localName = localName;
221
m_hashCode = toString().hashCode();
225
* Construct a QName from a string, resolving the prefix
226
* using the given namespace stack. The default namespace is
229
* @param qname Qualified name to resolve
230
* @param namespaces Namespace stack to use to resolve namespace
232
public QName(String qname, Stack namespaces)
234
this(qname, namespaces, false);
238
* Construct a QName from a string, resolving the prefix
239
* using the given namespace stack. The default namespace is
242
* @param qname Qualified name to resolve
243
* @param namespaces Namespace stack to use to resolve namespace
244
* @param validate If true the new QName will be validated and an IllegalArgumentException will
245
* be thrown if it is invalid.
247
public QName(String qname, Stack namespaces, boolean validate)
250
String namespace = null;
251
String prefix = null;
252
int indexOfNSSep = qname.indexOf(':');
254
if (indexOfNSSep > 0)
256
prefix = qname.substring(0, indexOfNSSep);
258
if (prefix.equals("xml"))
260
namespace = S_XMLNAMESPACEURI;
263
else if (prefix.equals("xmlns"))
269
int depth = namespaces.size();
271
for (int i = depth - 1; i >= 0; i--)
273
NameSpace ns = (NameSpace) namespaces.elementAt(i);
277
if ((null != ns.m_prefix) && prefix.equals(ns.m_prefix))
279
namespace = ns.m_uri;
290
if (null == namespace)
292
throw new RuntimeException(
293
XMLMessages.createXMLMessage(
294
XMLErrorResources.ER_PREFIX_MUST_RESOLVE,
295
new Object[]{ prefix })); //"Prefix must resolve to a namespace: "+prefix);
299
_localName = (indexOfNSSep < 0)
300
? qname : qname.substring(indexOfNSSep + 1);
304
if ((_localName == null) || (!XML11Char.isXML11ValidNCName(_localName)))
306
throw new IllegalArgumentException(XMLMessages.createXMLMessage(
307
XMLErrorResources.ER_ARG_LOCALNAME_INVALID,null )); //"Argument 'localName' not a valid NCName");
310
_namespaceURI = namespace;
312
m_hashCode = toString().hashCode();
316
* Construct a QName from a string, resolving the prefix
317
* using the given namespace context and prefix resolver.
318
* The default namespace is not resolved.
320
* @param qname Qualified name to resolve
321
* @param namespaceContext Namespace Context to use
322
* @param resolver Prefix resolver for this context
324
public QName(String qname, Element namespaceContext,
325
PrefixResolver resolver)
327
this(qname, namespaceContext, resolver, false);
331
* Construct a QName from a string, resolving the prefix
332
* using the given namespace context and prefix resolver.
333
* The default namespace is not resolved.
335
* @param qname Qualified name to resolve
336
* @param namespaceContext Namespace Context to use
337
* @param resolver Prefix resolver for this context
338
* @param validate If true the new QName will be validated and an IllegalArgumentException will
339
* be thrown if it is invalid.
341
public QName(String qname, Element namespaceContext,
342
PrefixResolver resolver, boolean validate)
345
_namespaceURI = null;
347
int indexOfNSSep = qname.indexOf(':');
349
if (indexOfNSSep > 0)
351
if (null != namespaceContext)
353
String prefix = qname.substring(0, indexOfNSSep);
357
if (prefix.equals("xml"))
359
_namespaceURI = S_XMLNAMESPACEURI;
363
else if (prefix.equals("xmlns"))
369
_namespaceURI = resolver.getNamespaceForPrefix(prefix,
373
if (null == _namespaceURI)
375
throw new RuntimeException(
376
XMLMessages.createXMLMessage(
377
XMLErrorResources.ER_PREFIX_MUST_RESOLVE,
378
new Object[]{ prefix })); //"Prefix must resolve to a namespace: "+prefix);
384
// TODO: error or warning...
388
_localName = (indexOfNSSep < 0)
389
? qname : qname.substring(indexOfNSSep + 1);
393
if ((_localName == null) || (!XML11Char.isXML11ValidNCName(_localName)))
395
throw new IllegalArgumentException(XMLMessages.createXMLMessage(
396
XMLErrorResources.ER_ARG_LOCALNAME_INVALID,null )); //"Argument 'localName' not a valid NCName");
400
m_hashCode = toString().hashCode();
405
* Construct a QName from a string, resolving the prefix
406
* using the given namespace stack. The default namespace is
409
* @param qname Qualified name to resolve
410
* @param resolver Prefix resolver for this context
412
public QName(String qname, PrefixResolver resolver)
414
this(qname, resolver, false);
418
* Construct a QName from a string, resolving the prefix
419
* using the given namespace stack. The default namespace is
422
* @param qname Qualified name to resolve
423
* @param resolver Prefix resolver for this context
424
* @param validate If true the new QName will be validated and an IllegalArgumentException will
425
* be thrown if it is invalid.
427
public QName(String qname, PrefixResolver resolver, boolean validate)
430
String prefix = null;
431
_namespaceURI = null;
433
int indexOfNSSep = qname.indexOf(':');
435
if (indexOfNSSep > 0)
437
prefix = qname.substring(0, indexOfNSSep);
439
if (prefix.equals("xml"))
441
_namespaceURI = S_XMLNAMESPACEURI;
445
_namespaceURI = resolver.getNamespaceForPrefix(prefix);
448
if (null == _namespaceURI)
450
throw new RuntimeException(
451
XMLMessages.createXMLMessage(
452
XMLErrorResources.ER_PREFIX_MUST_RESOLVE,
453
new Object[]{ prefix })); //"Prefix must resolve to a namespace: "+prefix);
455
_localName = qname.substring(indexOfNSSep + 1);
457
else if (indexOfNSSep == 0)
459
throw new RuntimeException(
460
XMLMessages.createXMLMessage(
461
XMLErrorResources.ER_NAME_CANT_START_WITH_COLON,
471
if ((_localName == null) || (!XML11Char.isXML11ValidNCName(_localName)))
473
throw new IllegalArgumentException(XMLMessages.createXMLMessage(
474
XMLErrorResources.ER_ARG_LOCALNAME_INVALID,null )); //"Argument 'localName' not a valid NCName");
479
m_hashCode = toString().hashCode();
484
* Returns the namespace URI. Returns null if the namespace URI
487
* @return The namespace URI, or null
489
public String getNamespaceURI()
491
return _namespaceURI;
495
* Returns the namespace prefix. Returns null if the namespace
496
* prefix is not known.
498
* @return The namespace prefix, or null
500
public String getPrefix()
506
* Returns the local part of the qualified name.
508
* @return The local part of the qualified name
510
public String getLocalName()
516
* Return the string representation of the qualified name, using the
517
* prefix if available, or the '{ns}foo' notation if not. Performs
518
* string concatenation, so beware of performance issues.
520
* @return the string representation of the namespace
522
public String toString()
525
return _prefix != null
526
? (_prefix + ":" + _localName)
527
: (_namespaceURI != null
528
? ("{"+_namespaceURI + "}" + _localName) : _localName);
532
* Return the string representation of the qualified name using the
533
* the '{ns}foo' notation. Performs
534
* string concatenation, so beware of performance issues.
536
* @return the string representation of the namespace
538
public String toNamespacedString()
541
return (_namespaceURI != null
542
? ("{"+_namespaceURI + "}" + _localName) : _localName);
547
* Get the namespace of the qualified name.
549
* @return the namespace URI of the qualified name
551
public String getNamespace()
553
return getNamespaceURI();
557
* Get the local part of the qualified name.
559
* @return the local part of the qualified name
561
public String getLocalPart()
563
return getLocalName();
567
* Return the cached hashcode of the qualified name.
569
* @return the cached hashcode of the qualified name
571
public int hashCode()
577
* Override equals and agree that we're equal if
578
* the passed object is a string and it matches
579
* the name of the arg.
581
* @param ns Namespace URI to compare to
582
* @param localPart Local part of qualified name to compare to
584
* @return True if the local name and uri match
586
public boolean equals(String ns, String localPart)
589
String thisnamespace = getNamespaceURI();
591
return getLocalName().equals(localPart)
592
&& (((null != thisnamespace) && (null != ns))
593
? thisnamespace.equals(ns)
594
: ((null == thisnamespace) && (null == ns)));
598
* Override equals and agree that we're equal if
599
* the passed object is a QName and it matches
600
* the name of the arg.
602
* @return True if the qualified names are equal
604
public boolean equals(Object object)
610
if (object instanceof QName) {
611
QName qname = (QName) object;
612
String thisnamespace = getNamespaceURI();
613
String thatnamespace = qname.getNamespaceURI();
615
return getLocalName().equals(qname.getLocalName())
616
&& (((null != thisnamespace) && (null != thatnamespace))
617
? thisnamespace.equals(thatnamespace)
618
: ((null == thisnamespace) && (null == thatnamespace)));
625
* Given a string, create and return a QName object
628
* @param name String to use to create QName
630
* @return a QName object
632
public static QName getQNameFromString(String name)
635
StringTokenizer tokenizer = new StringTokenizer(name, "{}", false);
637
String s1 = tokenizer.nextToken();
638
String s2 = tokenizer.hasMoreTokens() ? tokenizer.nextToken() : null;
641
qname = new QName(null, s1);
643
qname = new QName(s1, s2);
649
* This function tells if a raw attribute name is a
652
* @param attRawName Raw name of attribute
654
* @return True if the attribute starts with or is equal to xmlns
656
public static boolean isXMLNSDecl(String attRawName)
659
return (attRawName.startsWith("xmlns")
660
&& (attRawName.equals("xmlns")
661
|| attRawName.startsWith("xmlns:")));
665
* This function tells if a raw attribute name is a
668
* @param attRawName Raw name of attribute
670
* @return Prefix of attribute
672
public static String getPrefixFromXMLNSDecl(String attRawName)
675
int index = attRawName.indexOf(':');
677
return (index >= 0) ? attRawName.substring(index + 1) : "";
681
* Returns the local name of the given node.
683
* @param qname Input name
685
* @return Local part of the name if prefixed, or the given name if not
687
public static String getLocalPart(String qname)
690
int index = qname.indexOf(':');
692
return (index < 0) ? qname : qname.substring(index + 1);
696
* Returns the local name of the given node.
698
* @param qname Input name
700
* @return Prefix of name or empty string if none there
702
public static String getPrefixPart(String qname)
705
int index = qname.indexOf(':');
707
return (index >= 0) ? qname.substring(0, index) : "";