1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtXmlPatterns module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 /*
41  * QXmlName is conceptually identical to QPatternist::QName. The
42  * difference is that the latter is elegant, powerful and fast.
43  *
44  * However, it is too powerful and too open and not at all designed
45  * for being public. QXmlName, in contrast, is only a public marker,
46  * that for instance uses a qint64 instead of qint32, such that we in
47  * the future can use that, if needed.
48  */
49 
50 #include "qnamepool_p.h"
51 #include "qxmlname.h"
52 #include "qxmlnamepool.h"
53 #include "qxpathhelper_p.h"
54 #include "private/qxmlutils_p.h"
55 
56 QT_BEGIN_NAMESPACE
57 
58 /*!
59   \class QXmlName
60   \brief The QXmlName class represents the name of an XML node, in an efficient, namespace-aware way.
61   \reentrant
62   \since 4.4
63   \ingroup xml-tools
64   \inmodule QtXmlPatterns
65   QXmlName represents the name of an XML node in a way that
66   is both efficient and safe for comparing names. Normally,
67   an XML node represents an XML element or attribute, but
68   QXmlName can also represent the names of other kinds of
69   nodes, e.g., QAbstractXmlReceiver::processingInstruction()
70   and QAbstractXmlReceiver::namespaceBinding().
71 
72   The name of an XML node has three components: The \e {namespace
73   URI}, the \e {local name}, and the \e {prefix}. To see what these
74   refer to in XML, consider the following snippet.
75 
76   \quotefile patternist/mobeyDick.xml
77 
78   For the element named \e book, localName() returns \e book,
79   namespaceUri() returns \e http://example.com/MyDefault,
80   and prefix() returns an empty string. For the element named
81   \e title, localName() returns \e title, namespaceUri() returns
82   \e http://purl.org/dc/elements/1.1, and prefix() returns \e dc.
83 
84   To ensure that operations with QXmlName are efficient, e.g.,
85   copying names and comparing them, each instance of QXmlName is
86   associated with a \l {QXmlNamePool} {name pool}, which must be
87   specified at QXmlName construction time. The three components
88   of the QXmlName, i.e., the namespace URI, the local name, and
89   the prefix, are stored in the name pool mapped to identifiers
90   so they can be shared. For this reason, the only way to create
91   a valid instance of QXmlName is to use the class constructor,
92   where the \l {QXmlNamePool} {name pool}, local name, namespace
93   URI, and prefix must all be specified.
94 
95   Note that QXmlName's default constructor constructs a null
96   instance. It is typically used for allocating unused entries
97   in collections of QXmlName.
98 
99   A side effect of associating each instance of QXmlName with
100   a \l {QXmlNamePool} {name pool} is that each instance of
101   QXmlName is tied to the QXmlNamePool with which it was created.
102   However, the QXmlName class does not keep track of the name pool,
103   so all the accessor functions, e.g., namespaceUri(), prefix(),
104   localName(), and toClarkName() require that the correct name
105   pool be passed to them. Failure to provide the correct name
106   pool to these accessor functions results in undefined behavior.
107 
108   Note that a \l {QXmlNamePool} {name pool} is \e not an XML
109   namespace. One \l {QXmlNamePool} {name pool} can represent
110   instances of QXmlName from different XML namespaces, and the
111   instances of QXmlName from one XML namespace can be distributed
112   over multiple  \l {QXmlNamePool} {name pools}.
113 
114   \target Comparing QXmlNames
115   \section1 Comparing QXmlNames
116 
117   To determine what a QXmlName refers to, the \e {namespace URI}
118   and the \e {local name} are used. The \e prefix is not used
119   because the prefix is simply a shorthand name for use in place
120   of the normally much longer namespace URI. Nor is the prefix
121   used in name comparisons. For example, the following two element
122   nodes represent the same element and compare equal.
123 
124   \quotefile patternist/svgDocumentElement.xml
125 
126   \quotefile patternist/xsvgDocumentElement.xml
127 
128   Although the second name has the prefix \e x, the two names compare
129   equal as instances of QXmlName, because the prefix is not used in
130   the comparison.
131 
132   A local name can never be an empty string, although the prefix and
133   namespace URI can. If the prefix is not empty, the namespace URI
134   cannot be empty. Local names and prefixes must be valid
135   \l {http://www.w3.org/TR/REC-xml-names/#NT-NCName} {NCNames},
136   e.g., \e abc.def or \e abc123.
137 
138   QXmlName represents what is sometimes called an \e {expanded QName},
139   or simply a QName.
140 
141   \sa {http://www.w3.org/TR/REC-xml-names/#NT-NCName}{Namespaces in XML 1.0 (Second Edition), [4] NCName}
142  */
143 
144 /*!
145    \enum QXmlName::Constant
146    \internal
147    Various constants used in the QPatternist::NamePool and QXmlName.
148 
149    Setting of the mask enums use essentially this:
150 
151    \quotefile code/src_xmlpatterns_api_qxmlname.cpp
152 
153    The masks, such as LocalNameMask, are positive. That is, for the
154    area which the name resides, the bits are set.
155  */
156 
157 /*!
158  Constructs a QXmlName instance that inserts \a localName,
159  \a namespaceURI and \a prefix into \a namePool if they aren't
160  already there. The accessor functions namespaceUri(), prefix(),
161  localName(), and toClarkName() must be passed the \a namePool
162  used here, so the \a namePool must remain in scope while the
163  accessor functions might be used. However, two instances can
164  be compared with \e {==} or \e {!=} and copied without the
165  \a namePool.
166 
167  The user guarantees that the string components are valid for a
168  QName. In particular, the local name, and the prefix (if present),
169  must be valid \l {http://www.w3.org/TR/REC-xml-names/#NT-NCName}
170  {NCNames}. The function isNCName() can be used to test validity
171  of these names. The namespace URI should be an absolute URI.
172  QUrl::isRelative() can be used to test whether the namespace URI
173  is relative or absolute. Finally, providing a prefix is not valid
174  when no namespace URI is provided.
175 
176  \a namePool is not copied. Nor is the reference to it retained
177  in this instance. This constructor inserts the three strings
178  into \a namePool.
179  */
QXmlName(QXmlNamePool & namePool,const QString & localName,const QString & namespaceURI,const QString & prefix)180 QXmlName::QXmlName(QXmlNamePool &namePool,
181                    const QString &localName,
182                    const QString &namespaceURI,
183                    const QString &prefix)
184 {
185     Q_ASSERT_X(prefix.isEmpty() || QXmlUtils::isNCName(prefix), Q_FUNC_INFO,
186                "The prefix is invalid, maybe the arguments were mixed up?");
187     Q_ASSERT_X(QXmlUtils::isNCName(localName), Q_FUNC_INFO,
188                "The local name is invalid, maybe the arguments were mixed up?");
189 
190     m_qNameCode = namePool.d->allocateQName(namespaceURI, localName, prefix).code();
191 }
192 
193 /*!
194   \typedef QXmlName::Code
195   \internal
196 
197    Stores the \l {QXmlNamePool} {name pool} identifiers for
198    the namespace URI, local name, and prefix.
199  */
200 
201 /*!
202   Returns true if this QXmlName is not initialized with a
203   valid combination of \e {namespace URI}, \e {local name},
204   and \e {prefix}.
205 
206   A valid local name is always required. The prefix and
207   namespace URI can be empty, but if the prefix is not empty,
208   the namespace URI must not be empty. Local names and
209   prefixes must be valid
210   \l {http://www.w3.org/TR/REC-xml-names/#NT-NCName} {NCNames},
211   e.g., \e abc.def or \e abc123.
212  */
isNull() const213 bool QXmlName::isNull() const
214 {
215     return m_qNameCode == InvalidCode;
216 }
217 
218 /*!
219   Constructs an uninitialized QXmlName. To build
220   a valid QXmlName, you normally use the other constructor, which
221   takes a \l {QXmlNamePool} {name pool}, namespace URI, local name,
222   and prefix as parameters. But you can also use this constructor
223   to build a null QXmlName and then assign an existing QXmlName
224   to it.
225 
226   \sa isNull()
227  */
QXmlName()228 QXmlName::QXmlName() : m_qNameCode(InvalidCode)
229 {
230 }
231 
232 /*!
233   \fn QXmlName::QXmlName(const NamespaceCode uri,
234                          const LocalNameCode ln,
235                          const PrefixCode p = 0)
236   \internal
237  */
238 
239 /*!
240   \fn QXmlName::hasPrefix() const
241   \internal
242 
243   Returns true if this QXmlName has a non-empty prefix. If this
244   function returns true, hasNamespace() will also return true,
245   because a QXmlName can't have a prefix if it doesn't have a
246   namespace URI.
247  */
248 
249 /*!
250   \fn bool QXmlName::hasNamespace() const
251   \internal
252 
253   Returns true if this QXmlName has a non-empty namespace URI.
254  */
255 
256 /*!
257   \fn Code QXmlName::code() const
258   \internal
259 
260   Returns the internal code that contains the id codes for the
261   local name, prefix and namespace URI. It is opaque when used
262   outside QXmlName, but it can be useful when one wants to put
263   a QXmlName in a hash, and the prefix is significant.
264  */
265 
266 /*!
267   Returns true if this QXmlName is equal to \a other; otherwise false.
268   Two QXmlNames are equal if their namespace URIs are the same \e and
269   their local names are the same. The prefixes are ignored.
270 
271   Note that it is meaningless to compare two instances of QXmlName
272   that were created with different \l {QXmlNamePool} {name pools},
273   but the attempt is not detected and the behavior is undefined.
274 
275   \sa operator!=()
276  */
operator ==(const QXmlName & other) const277 bool QXmlName::operator==(const QXmlName &other) const
278 {
279     return (m_qNameCode & ExpandedNameMask) == (other.m_qNameCode & ExpandedNameMask);
280 }
281 
282 /*!
283   Returns true if this QXmlName is \e not equal to \a other;
284   otherwise false. Two QXmlNames are equal if their namespace
285   URIs are the same \e and their local names are the same. They
286   are not equal if either their namespace URIs differ or their
287   local names differ. Their prefixes are ignored.
288 
289   Note that it is meaningless to compare two instances of QXmlName
290   that were created with different \l {QXmlNamePool} {name pools},
291   but the attempt is not detected and the behavior is undefined.
292 
293   \sa operator==()
294  */
operator !=(const QXmlName & other) const295 bool QXmlName::operator!=(const QXmlName &other) const
296 {
297     return !operator==(other);
298 }
299 
300 /*!
301   \fn bool QXmlName::isLexicallyEqual(const QXmlName &other) const
302   \internal
303 
304   Returns true if this and \a other are lexically equal. Two
305   QXmlNames are lexically equal if their local names are equal
306   \e and their prefixes are equal.
307  */
308 
309 /*!
310  \fn uint qHash(const QXmlName &name)
311  \since 4.4
312  \relates QXmlName
313 
314  Computes a hash key from the local name and the namespace
315  URI in \a name. The prefix in \a name is not used in the computation.
316  */
qHash(const QXmlName & name)317 uint qHash(const QXmlName &name)
318 {
319     return name.m_qNameCode & QXmlName::ExpandedNameMask;
320 }
321 
322 /*!
323  Returns the namespace URI.
324 
325  Note that for efficiency, the namespace URI string is not
326  stored in the QXmlName but in the \l {QXmlNamePool} that was
327  passed to the constructor. Hence, that same \a namePool must
328  be passed to this function, so it can be used for looking up
329  the namespace URI.
330  */
namespaceUri(const QXmlNamePool & namePool) const331 QString QXmlName::namespaceUri(const QXmlNamePool &namePool) const
332 {
333     if(isNull())
334         return QString();
335     else
336         return namePool.d->stringForNamespace(namespaceURI());
337 }
338 
339 /*!
340  Returns the prefix.
341 
342  Note that for efficiency, the prefix string is not stored in
343  the QXmlName but in the \l {QXmlNamePool} that was passed to
344  the constructor. Hence, that same \a namePool must be passed
345  to this function, so it can be used for looking up the prefix.
346  */
prefix(const QXmlNamePool & namePool) const347 QString QXmlName::prefix(const QXmlNamePool &namePool) const
348 {
349     if(isNull())
350         return QString();
351     else
352         return namePool.d->stringForPrefix(prefix());
353 }
354 
355 /*!
356  Returns the local name.
357 
358  Note that for efficiency, the local name string is not stored
359  in the QXmlName but in the \l {QXmlNamePool} that was passed to
360  the constructor. Hence, that same \a namePool must be passed
361  to this function, so it can be used for looking up the
362  local name.
363  */
localName(const QXmlNamePool & namePool) const364 QString QXmlName::localName(const QXmlNamePool &namePool) const
365 {
366     if(isNull())
367         return QString();
368     else
369         return namePool.d->stringForLocalName(localName());
370 }
371 
372 /*!
373   Returns this QXmlName formatted as a Clark Name. For example,
374   if the local name is \c html, the prefix is \c x, and the
375   namespace URI is \c {http://www.w3.org/1999/xhtml/},
376   then the Clark Name returned is:
377 
378   \code
379   {http://www.w3.org/1999/xhtml/}x:html.
380   \endcode
381 
382   If the local name is \e {MyWidget} and the namespace is empty,
383   the Clark Name returned is:
384 
385   \code
386   MyWidget
387   \endcode
388 
389   Note that for efficiency, the namespace URI, local name, and
390   prefix strings are not stored in the QXmlName but in the
391   \l {QXmlNamePool} that was passed to the constructor. Hence,
392   that same \a namePool must be passed to this function, so it
393   can be used for looking up the three string components.
394 
395   This function can be useful for debugging.
396 
397  \sa {http://www.jclark.com/xml/xmlns.htm}{XML Namespaces, James Clark}, fromClarkName()
398  */
toClarkName(const QXmlNamePool & namePool) const399 QString QXmlName::toClarkName(const QXmlNamePool &namePool) const
400 {
401     return namePool.d->toClarkName(*this);
402 }
403 
404 /*!
405     Constructs a copy of \a other.
406 
407     \sa operator=()
408     \since 5.9
409 */
410 QXmlName::QXmlName(const QXmlName &) = default; // ### Qt 6: remove
411 
412 /*!
413   Assigns \a other to \e this and returns \e this.
414  */
415 QXmlName &QXmlName::operator=(const QXmlName &) = default; // ### Qt 6: remove
416 
417 /*!
418  Returns true if \a candidate is an \c NCName. An \c NCName
419  is a string that can be used as a name in XML and XQuery,
420  e.g., the prefix or local name in an element or attribute,
421  or the name of a variable.
422 
423  \sa {http://www.w3.org/TR/REC-xml-names/#NT-NCName}{Namespaces in XML 1.0 (Second Edition), [4] NCName}
424  */
isNCName(const QString & candidate)425 bool QXmlName::isNCName(const QString &candidate)
426 {
427     return QXmlUtils::isNCName(candidate);
428 }
429 
430 /*!
431   Converts \a clarkName into a QXmlName, inserts into \a namePool, and
432   returns it.
433 
434   A clark name is a way to present a full QName with only one string, where
435   the namespace cannot contain braces. Here are a couple of examples:
436 
437     \table
438     \header
439         \li Clark Name
440         \li Description
441     \row
442         \li \c html
443         \li The local name \c html, in no namespace
444     \row
445         \li \c {http://www.w3.org/1999/xhtml}html
446         \li The local name \c html, in the XHTML namespace
447     \row
448         \li \c {http://www.w3.org/1999/xhtml}my:html
449         \li The local name \c html, in the XHTML namespace, with the prefix \c my
450     \endtable
451 
452     If the namespace contains braces, the returned value is either invalid or
453     has undefined content.
454 
455     If \a clarkName is an invalid name, a default constructed QXmlName is
456     returned.
457 
458   \since 4.5
459   \sa toClarkName()
460  */
fromClarkName(const QString & clarkName,const QXmlNamePool & namePool)461 QXmlName QXmlName::fromClarkName(const QString &clarkName,
462                                  const QXmlNamePool &namePool)
463 {
464     return namePool.d->fromClarkName(clarkName);
465 }
466 
467 /*!
468   \typedef QXmlName::LocalNameCode
469   \internal
470  */
471 
472 /*!
473   \typedef QXmlName::PrefixCode
474   \internal
475  */
476 
477 /*!
478   \typedef QXmlName::NamespaceCode
479   \internal
480  */
481 
482 /*!
483   \fn void QXmlName::setLocalName(const LocalNameCode c)
484   \internal
485 */
486 
487 /*!
488   \fn LocalNameCode QXmlName::localName() const
489   \internal
490 */
491 
492 /*!
493   \fn PrefixCode QXmlName::prefix() const
494   \internal
495 */
496 
497 /*!
498   \fn NamespaceCode QXmlName::namespaceURI() const
499   \internal
500 */
501 
502 /*!
503   \fn void QXmlName::setNamespaceURI(const NamespaceCode c)
504   \internal
505 */
506 
507 /*!
508   \fn void QXmlName::setPrefix(const PrefixCode c)
509   \internal
510 */
511 QT_END_NAMESPACE
512 
513