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 // W A R N I N G 42 // ------------- 43 // 44 // This file is not part of the Qt API. It exists purely as an 45 // implementation detail. This header file may change from version to 46 // version without notice, or even be removed. 47 // 48 // We mean it. 49 50 #ifndef Patternist_QNameConstructor_H 51 #define Patternist_QNameConstructor_H 52 53 #include <private/qsinglecontainer_p.h> 54 #include <private/qbuiltintypes_p.h> 55 #include <private/qpatternistlocale_p.h> 56 #include <private/qxpathhelper_p.h> 57 58 QT_BEGIN_NAMESPACE 59 60 namespace QPatternist 61 { 62 /** 63 * @short Creates an @c xs:QName value from a lexical QName using 64 * statically known namespace bindings. 65 * 66 * @see QQNameValue 67 * @see QXmlUtils 68 * @author Frans Englich <frans.englich@nokia.com> 69 * @ingroup Patternist_expressions 70 */ 71 class QNameConstructor : public SingleContainer 72 { 73 public: 74 75 QNameConstructor(const Expression::Ptr &source, 76 const NamespaceResolver::Ptr &nsResolver); 77 78 virtual Item evaluateSingleton(const DynamicContext::Ptr &) const; 79 80 virtual SequenceType::List expectedOperandTypes() const; 81 82 virtual SequenceType::Ptr staticType() const; 83 84 virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; 85 86 /** 87 * Expands @p lexicalQName, which is a lexical representation of a QName such as "x:body", into 88 * a QName using @p nsResolver to supply the namespace bindings. 89 * 90 * If @p lexicalQName is lexically invalid @p InvalidQName is raised via @p context, or if 91 * no namespace binding does not exists for a prefix(if any) in @p lexicalQName, @p NoBinding 92 * is raised via @p context. 93 * 94 * If @p asForAttribute is @c true, the name is considered to be for an 95 * attribute in some way, and @p lexicalQName will not pick up the 96 * default namespace if it doesn't have a prefix. 97 * 98 * @p nsResolver is parameterized meaning the function can be instantiated with either 99 * DynamicContext or StaticContext. 100 * 101 * @see QQNameValue 102 * @see QXmlUtils 103 */ 104 template<typename TReportContext, 105 const ReportContext::ErrorCode InvalidQName, 106 const ReportContext::ErrorCode NoBinding> 107 static 108 QXmlName expandQName(const QString &lexicalQName, 109 const TReportContext &context, 110 const NamespaceResolver::Ptr &nsResolver, 111 const SourceLocationReflection *const r, 112 const bool asForAttribute = false); 113 114 /** 115 * Resolves the namespace prefix @p prefix to its namespace if it exists, or 116 * raised ReportContext::XPST0081 otherwise. 117 * 118 * @returns the namespace URI corresponding to @p prefix 119 */ 120 static QXmlName::NamespaceCode namespaceForPrefix(const QXmlName::PrefixCode prefix, 121 const StaticContext::Ptr &context, 122 const SourceLocationReflection *const r); 123 124 virtual const SourceLocationReflection *actualReflection() const; 125 126 private: 127 const NamespaceResolver::Ptr m_nsResolver; 128 }; 129 130 template<typename TReportContext, 131 const ReportContext::ErrorCode InvalidQName, 132 const ReportContext::ErrorCode NoBinding> expandQName(const QString & lexicalQName,const TReportContext & context,const NamespaceResolver::Ptr & nsResolver,const SourceLocationReflection * const r,const bool asForAttribute)133 QXmlName QNameConstructor::expandQName(const QString &lexicalQName, 134 const TReportContext &context, 135 const NamespaceResolver::Ptr &nsResolver, 136 const SourceLocationReflection *const r, 137 const bool asForAttribute) 138 { 139 Q_ASSERT(nsResolver); 140 Q_ASSERT(context); 141 142 if(XPathHelper::isQName(lexicalQName)) 143 { 144 QString prefix; 145 QString local; 146 XPathHelper::splitQName(lexicalQName, prefix, local); 147 const QXmlName::NamespaceCode nsCode = asForAttribute && prefix.isEmpty() ? QXmlName::NamespaceCode(StandardNamespaces::empty) 148 : (nsResolver->lookupNamespaceURI(context->namePool()->allocatePrefix(prefix))); 149 150 if(nsCode == NamespaceResolver::NoBinding) 151 { 152 context->error(QtXmlPatterns::tr("No namespace binding exists for " 153 "the prefix %1 in %2").arg(formatKeyword(prefix), 154 formatKeyword(lexicalQName)), 155 NoBinding, 156 r); 157 return QXmlName(); /* Silence compiler warning. */ 158 } 159 else 160 return context->namePool()->allocateQName(context->namePool()->stringForNamespace(nsCode), local, prefix); 161 } 162 else 163 { 164 context->error(QtXmlPatterns::tr("%1 is an invalid %2") 165 .arg(formatData(lexicalQName)) 166 .arg(formatType(context->namePool(), BuiltinTypes::xsQName)), 167 InvalidQName, 168 r); 169 return QXmlName(); /* Silence compiler warning. */ 170 } 171 } 172 } 173 174 QT_END_NAMESPACE 175 176 #endif 177