Qt 4.8
qxslttokenizer.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
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 Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include <QStringList>
43 
44 #include "qbuiltintypes_p.h"
45 #include "qcommonnamespaces_p.h"
47 #include "qxquerytokenizer_p.h"
48 #include "qpatternistlocale_p.h"
49 
50 #include "qxslttokenizer_p.h"
51 
53 
54 using namespace QPatternist;
55 
57 {
58  if(m_hasDelivered)
60  else
61  {
62  *location = m_location;
63  m_hasDelivered = true;
64  return m_token;
65  }
66 }
67 
69  const QUrl &location,
70  const ReportContext::Ptr &context,
71  const NamePool::Ptr &np) : Tokenizer(location)
72  , MaintainingReader<XSLTTokenLookup>(createElementDescriptions(), createStandardAttributes(), context, queryDevice)
73  , m_location(location)
74  , m_namePool(np)
75  /* We initialize after all name constants. */
76  , m_validationAlternatives(createValidationAlternatives())
77  , m_parseInfo(0)
78 {
80 
82 }
83 
85 {
87 }
88 
90 {
91  m_parseInfo = parseInfo;
92 }
93 
95 {
97 }
98 
100 {
101  QSet<NodeName> retval;
102  enum
103  {
104  ReservedForAttributes = 6
105  };
106 
107  retval.reserve(6);
108 
109  retval.insert(DefaultCollation);
112  retval.insert(UseWhen);
113  retval.insert(Version);
115 
116  Q_ASSERT(retval.count() == ReservedForAttributes);
117 
118  return retval;
119 }
120 
122 {
124  enum
125  {
126  ReservedForElements = 40
127  };
128  result.reserve(ReservedForElements);
129 
130  /* xsl:apply-templates */
131  {
135  }
136 
137  /* xsl:template */
138  {
145  }
146 
147  /* xsl:text, xsl:choose and xsl:otherwise */
148  {
150  result.insert(Choose, e);
151  result.insert(Otherwise, e);
152  }
153 
154  /* xsl:stylesheet */
155  {
157 
159 
167  }
168 
169  /* xsl:transform */
170  {
171  result[Transform] = result[Stylesheet];
172  }
173 
174  /* xsl:value-of */
175  {
179  }
180 
181  /* xsl:variable */
182  {
184 
186 
189  }
190 
191  /* xsl:when & xsl:if */
192  {
194 
196 
197  result.insert(If, e);
198  }
199 
200  /* xsl:sequence, xsl:for-each */
201  {
203 
205 
206  result.insert(ForEach, e);
207  }
208 
209  /* xsl:comment */
210  {
212 
214  }
215 
216  /* xsl:processing-instruction */
217  {
219 
222  }
223 
224  /* xsl:document */
225  {
227 
230  }
231 
232  /* xsl:element */
233  {
235 
237 
243  }
244 
245  /* xsl:attribute */
246  {
248 
250 
256  }
257 
258  /* xsl:function */
259  {
261 
263 
266  }
267 
268  /* xsl:param */
269  {
271 
273 
278  }
279 
280  /* xsl:namespace */
281  {
283 
286  }
287 
288  /* xsl:call-template */
289  {
292  }
293 
294  /* xsl:perform-sort */
295  {
298  }
299 
300  /* xsl:sort */
301  {
303 
312  }
313 
314  /* xsl:import-schema */
315  {
317 
321  }
322 
323  /* xsl:message */
324  {
326 
330  }
331 
332  /* xsl:copy-of */
333  {
335 
337 
342  }
343 
344  /* xsl:copy */
345  {
347 
354  }
355 
356  /* xsl:output */
357  {
359 
378  }
379 
380  /* xsl:attribute-set */
381  {
383 
386  }
387 
388  /* xsl:include and xsl:import. */
389  {
392  result[Import] = e;
393  }
394 
395  /* xsl:with-param */
396  {
399 
403  }
404 
405  /* xsl:strip-space */
406  {
409 
410  result.insert(PreserveSpace, e);
411  }
412 
413  /* xsl:result-document */
414  {
416 
437  }
438 
439  /* xsl:key */
440  {
442 
445 
448  }
449 
450  /* xsl:analyze-string */
451  {
453 
456 
458  }
459 
460  /* xsl:matching-substring */
461  {
462  /* We insert a default constructed value. */
463  result[MatchingSubstring];
464  }
465 
466  /* xsl:non-matching-substring */
467  {
468  /* We insert a default constructed value. */
469  result[NonMatchingSubstring];
470  }
471 
472  Q_ASSERT(result.count() == ReservedForElements);
473 
474  return result;
475 }
476 
478 {
479  QHash<QString, int> retval;
480 
481  retval.insert(QLatin1String("preserve"), 0);
482  retval.insert(QLatin1String("strip"), 1);
483  retval.insert(QLatin1String("strict"), 2);
484  retval.insert(QLatin1String("lax"), 3);
485 
486  return retval;
487 }
488 
490 {
491  return m_stripWhitespace.top() && isWhitespace();
492 }
493 
495 {
496  QString message;
497 
498  ReportContext::ErrorCode effectiveCode = code;
499 
500  switch(tokenType())
501  {
503  {
504  if(isXSLT())
505  {
506  switch(currentElementName())
507  {
508  case Include:
509  effectiveCode = ReportContext::XTSE0170;
510  break;
511  case Import:
512  effectiveCode = ReportContext::XTSE0190;
513  break;
514  default:
515  ;
516  }
517  }
518 
519  message = QtXmlPatterns::tr("Element %1 is not allowed at this location.")
520  .arg(formatKeyword(name()));
521  break;
522  }
524  {
525  if(whitespaceToSkip())
526  return;
527 
528  message = QtXmlPatterns::tr("Text nodes are not allowed at this location.");
529  break;
530  }
532  {
533  /* It's an issue with well-formedness. */
534  message = escape(errorString());
535  break;
536  }
537  default:
538  Q_ASSERT(false);
539  }
540 
541  error(message, effectiveCode);
542 }
543 
545 {
546  if(hasError())
547  {
548  error(QtXmlPatterns::tr("Parse error: %1").arg(escape(errorString())), ReportContext::XTSE0010);
549  }
550 }
551 
553 {
554  QString result;
555 
556  while(!atEnd())
557  {
558  switch(readNext())
559  {
561  {
562  result += text().toString();
563  continue;
564  }
566  /* Fallthrough. */
568  continue;
570  return result;
571  default:
573  }
574  }
575 
577  return result;
578 }
579 
581 {
582  /* Do nothing, return a dummy value. */
583  return 0;
584 }
585 
587 {
588  /* Do nothing. */
589  Q_UNUSED(position);
590 }
591 
593  QStack<Token> *const queueOnExit,
594  const bool isXSLTElement,
595  const QXmlStreamAttributes *atts,
596  const bool generateCode,
597  const bool setGlobalVersion)
598 {
599  const QString ns(isXSLTElement ? QString() : CommonNamespaces::XSLT);
600  const QXmlStreamAttributes effectiveAtts(atts ? *atts : attributes());
601 
602  if(!effectiveAtts.hasAttribute(ns, QLatin1String("version")))
603  return;
604 
605  const QString attribute(effectiveAtts.value(ns, QLatin1String("version")).toString());
606  const AtomicValue::Ptr number(Decimal::fromLexical(attribute));
607 
608  if(number->hasError())
609  {
610  error(QtXmlPatterns::tr("The value of the XSL-T version attribute "
611  "must be a value of type %1, which %2 isn't.").arg(formatType(m_namePool, BuiltinTypes::xsDecimal),
612  formatData(attribute)),
614  }
615  else
616  {
617 
618  if(generateCode)
619  {
620  queueToken(Token(XSLT_VERSION, attribute), to);
622  }
623 
624  const xsDecimal version = number->as<Numeric>()->toDecimal();
625  if(version == 2.0)
627  else if(version == 1.0)
628  {
629  /* See section 3.6 Stylesheet Element discussing this. */
630  warning(QtXmlPatterns::tr("Running an XSL-T 1.0 stylesheet with a 2.0 processor."));
632 
633  if(setGlobalVersion)
634  {
637  }
638  }
639  else if(version > 2.0)
641  else if(version < 2.0)
643  }
644 
645  if(generateCode)
646  queueOnExit->push(CURLY_RBRACE);
647 }
648 
650  QStack<Token> *const queueOnExit,
651  const bool isInstruction,
652  const QXmlStreamAttributes *atts)
653 {
654  const QXmlStreamAttributes effectiveAtts(atts ? *atts : m_currentAttributes);
655 
656  if(effectiveAtts.hasAttribute(QLatin1String("xml:base")))
657  {
658  const QStringRef val(effectiveAtts.value(QLatin1String("xml:base")));
659 
660  if(!val.isEmpty())
661  {
662  if(isInstruction)
663  {
664  queueToken(BASEURI, to);
665  queueToken(Token(STRING_LITERAL, val.toString()), to);
667  queueOnExit->push(CURLY_RBRACE);
668  }
669  else
670  {
671  queueToken(DECLARE, to);
672  queueToken(BASEURI, to);
673  queueToken(INTERNAL, to);
674  queueToken(Token(STRING_LITERAL, val.toString()), to);
675  queueToken(SEMI_COLON, to);
676  }
677  }
678  }
679 }
680 
681 void XSLTTokenizer::handleStandardAttributes(const bool isXSLTElement)
682 {
683  /* We're not necessarily StartElement, that's why we have atts passed in. */
685 
687  return;
688 
690 
691  const QString ns(isXSLTElement ? QString() : CommonNamespaces::XSLT);
692  const int len = m_currentAttributes.count();
693 
694  for(int i = 0; i < len; ++i)
695  {
697 
698  if(att.qualifiedName() == QLatin1String("xml:space"))
699  {
701 
702  /* We raise an error if the value is not recognized.
703  *
704  * Extensible Markup Language (XML) 1.0 (Fourth Edition), 2.10
705  * White Space Handling:
706  *
707  * 'This specification does not give meaning to any value of
708  * xml:space other than "default" and "preserve". It is an error
709  * for other values to be specified; the XML processor may report
710  * the error or may recover by ignoring the attribute specification
711  * or by reporting the (erroneous) value to the application.' */
713  QLatin1String("default"),
714  QLatin1String("preserve"),
716  }
717 
718  if(att.namespaceUri() != ns)
719  continue;
720 
721  switch(toToken(att.name()))
722  {
723  case Type:
724  /* Fallthrough. */
725  case Validation:
726  /* Fallthrough. */
727  case UseAttributeSets:
728  /* Fallthrough. */
729  case Version:
730  /* These are handled by other function such as
731  * handleValidationAttributes() and handleXSLTVersion(). */
732  continue;
733  default:
734  {
735  if(!isXSLTElement) /* validateElement() will take care of it, and we
736  * don't want to flag non-standard XSL-T attributes. */
737  {
738  error(QtXmlPatterns::tr("Unknown XSL-T attribute %1.")
739  .arg(formatKeyword(att.name())),
741  }
742  }
743  }
744  }
745 }
746 
747 void XSLTTokenizer::handleValidationAttributes(const bool isLRE) const
748 {
750 
751  const QString ns(isLRE ? QString() : CommonNamespaces::XSLT);
752 
753  const bool hasValidation = hasAttribute(ns, QLatin1String("validation"));
754  const bool hasType = hasAttribute(ns, QLatin1String("type"));
755 
756  if(!hasType && !hasValidation)
757  return;
758 
759  if(hasType && hasValidation)
760  {
761  error(QtXmlPatterns::tr("Attribute %1 and %2 are mutually exclusive.")
762  .arg(formatKeyword(QLatin1String("validation")),
763  formatKeyword(QLatin1String("type"))),
765  }
766 
767  /* QXmlStreamReader surely doesn't make this easy. */
768  QXmlStreamAttribute validationAttribute;
769  int len = m_currentAttributes.count();
770 
771  for(int i = 0; i < len; ++i)
772  {
774  if(at.name() == QLatin1String("validation") && at.namespaceUri() == ns)
775  validationAttribute = at;
776  }
777 
778  Q_ASSERT_X(!validationAttribute.name().isNull(), Q_FUNC_INFO,
779  "We should always find the attribute.");
780 
781  /* We don't care about the return value, we just want to check it's a valid
782  * one. */
784  validationAttribute);
785 }
786 
788 {
789  Q_UNUSED(sourceLocator);
790 
791  if(m_tokenSource.isEmpty())
792  {
793  switch(m_state.top())
794  {
797  break;
800  break;
803  break;
804  }
805 
806  if(m_tokenSource.isEmpty())
807  {
808  *sourceLocator = currentSourceLocator();
809  return Token(END_OF_FILE);
810  }
811  else
812  return m_tokenSource.head()->nextToken(sourceLocator);
813  }
814  else
815  {
816  do
817  {
818  const Token candidate(m_tokenSource.head()->nextToken(sourceLocator));
819  if(candidate.type == END_OF_FILE)
821  else
822  return candidate;
823  }
824  while(!m_tokenSource.isEmpty());
825 
826  /* Now we will resume parsing inside the regular XSL-T(XML) file. */
827  return nextToken(sourceLocator);
828  }
829 }
830 
832 {
833  Q_ASSERT(isXSLT());
836 
837  return currentElementName() == name;
838 }
839 
840 inline bool XSLTTokenizer::isXSLT() const
841 {
844  Q_FUNC_INFO, "The current token state must be StartElement or EndElement.");
845  /* Possible optimization: let MaintainingReader set an m_isXSLT which we
846  * read. */
848 }
849 
851  TokenSource::Queue *const destination)
852 {
853  while(!source.isEmpty())
854  queueToken(source.pop(), destination);
855 }
856 
858 {
859  while(!atEnd())
860  {
861  switch(readNext())
862  {
864  {
865  /* First, we synthesize one of the built-in templates,
866  * see section 6.6 Built-in Template Rules.
867  *
868  * Note that insideStylesheetModule() can be called multiple
869  * times so we can't do it there. */
870  {
871  /* Start with the one for text nodes and attributes.
872  * declare template matches (text() | @*) mode #all
873  * {
874  * text{.}
875  * };
876  */
877 
878  /* declare template matches (text() | @*) */
890 
891  /* mode #all */
895 
896  /* text{.} { */
901 
902  /* }; */
905  }
906 
907  if(isXSLT() && isStylesheetElement())
908  {
910  QStack<Token> onExitTokens;
911  handleXMLBase(&m_tokenSource, &onExitTokens, false);
912  handleXSLTVersion(&m_tokenSource, &onExitTokens, true, 0, false, true);
913  validateElement();
915 
916  /* We're a regular stylesheet. */
917 
920  }
921  else
922  {
923  /* We're a simplified stylesheet. */
924 
926  {
927  error(QtXmlPatterns::tr("In a simplified stylesheet module, attribute %1 must be present.")
928  .arg(formatKeyword(QLatin1String("version"))),
930  }
931 
932  QStack<Token> onExitTokens;
933 
934  /* We synthesize this as exemplified in
935  * 3.7 Simplified Stylesheet Modules. */
944 
945  handleXSLTVersion(&m_tokenSource, &onExitTokens, false, 0, true);
947 
949 
950  queueOnExit(onExitTokens, &m_tokenSource);
954  }
955 
959 
960  break;
961  }
962  default:
963  /* Do nothing. */;
964  }
965  }
967 }
968 
970  TokenSource::Queue *const to)
971 {
972  TokenSource::Queue *const effective = to ? to : &m_tokenSource;
973 
975 }
976 
977 void XSLTTokenizer::pushState(const State nextState)
978 {
979  m_state.push(nextState);
980 }
981 
983 {
984  m_state.pop();
985 }
986 
988 {
989  const bool hasPriority = hasAttribute(QLatin1String("priority"));
990  const bool hasMatch = hasAttribute(QLatin1String("match"));
991  const bool hasName = hasAttribute(QLatin1String("name"));
992  const bool hasMode = hasAttribute(QLatin1String("mode"));
993  const bool hasAs = hasAttribute(QLatin1String("as"));
994 
995  if(!hasMatch &&
996  (hasMode ||
997  hasPriority))
998  {
999  error(QtXmlPatterns::tr("If element %1 has no attribute %2, it cannot have attribute %3 or %4.")
1000  .arg(formatKeyword(QLatin1String("template")),
1001  formatKeyword(QLatin1String("match")),
1002  formatKeyword(QLatin1String("mode")),
1003  formatKeyword(QLatin1String("priority"))),
1005  }
1006  else if(!hasMatch && !hasName)
1007  {
1008  error(QtXmlPatterns::tr("Element %1 must have at least one of the attributes %2 or %3.")
1009  .arg(formatKeyword(QLatin1String("template")),
1010  formatKeyword(QLatin1String("name")),
1011  formatKeyword(QLatin1String("match"))),
1013  }
1014 
1017 
1018  if(hasName)
1019  {
1022  }
1023 
1024  if(hasMatch)
1025  {
1028  }
1029 
1030  if(hasMode)
1031  {
1032  const QString modeString(readAttribute(QLatin1String("mode")).simplified());
1033 
1034  if(modeString.isEmpty())
1035  {
1036  error(QtXmlPatterns::tr("At least one mode must be specified in the %1-attribute on element %2.")
1037  .arg(formatKeyword(QLatin1String("mode")),
1038  formatKeyword(QLatin1String("template"))),
1040  }
1041 
1043 
1044  const QStringList modeList(modeString.split(QLatin1Char(' ')));
1045 
1046  for(int i = 0; i < modeList.count(); ++i)
1047  {
1048  const QString &mode = modeList.at(i);
1049 
1050  queueToken(Token(mode.contains(QLatin1Char(':')) ? QNAME : NCNAME, mode), &m_tokenSource);
1051 
1052  if(i < modeList.count() - 1)
1054  }
1055  }
1056 
1057  if(hasPriority)
1058  {
1061  }
1062 
1063  QStack<Token> onExitTokens;
1065 
1066  /* queueParams moves the reader so we need to freeze the attributes. */
1072 
1073  if(hasAs)
1074  {
1077  }
1078 
1080 
1081  handleXMLBase(&m_tokenSource, &onExitTokens, true, &atts);
1082  handleXSLTVersion(&m_tokenSource, &onExitTokens, true, &atts);
1085  insideSequenceConstructor(&m_tokenSource, onExitTokens, false);
1086  queueOnExit(onExitTokens, &m_tokenSource);
1087 }
1088 
1090  TokenSource::Queue *const to,
1091  const bool wrapWithParantheses)
1092 {
1093  TokenSource::Queue *const effectiveTo = to ? to : &m_tokenSource;
1094 
1095  if(wrapWithParantheses)
1096  queueToken(LPAREN, effectiveTo);
1097 
1098  effectiveTo->enqueue(TokenSource::Ptr(new XQueryTokenizer(expr, queryURI())));
1099 
1100  if(wrapWithParantheses)
1101  queueToken(RPAREN, effectiveTo);
1102 }
1103 
1105  TokenSource::Queue *const to)
1106 {
1107  queueToken(AVT, to);
1108  queueToken(LPAREN, to);
1111  queueToken(RPAREN, to);
1112 }
1113 
1115 {
1118 }
1119 
1121  TokenSource::Queue *const to)
1122 {
1123  if(hasWrittenExpression)
1124  queueToken(COMMA, to);
1125  else
1126  hasWrittenExpression = true;
1127 }
1128 
1130 {
1131  queueToken(LPAREN, to);
1132  queueToken(RPAREN, to);
1133 }
1134 
1136 {
1138  bool hasHandledOtherwise = false;
1139  bool hasEncounteredAtLeastOneWhen = false;
1140 
1141  while(!atEnd())
1142  {
1143  switch(readNext())
1144  {
1146  {
1147  if(isXSLT())
1148  {
1149  QStack<Token> onExitTokens;
1151  validateElement();
1152 
1153  switch(currentElementName())
1154  {
1155  case When:
1156  {
1157  if(hasHandledOtherwise)
1158  {
1159  error(QtXmlPatterns::tr("Element %1 must come last.")
1160  .arg(formatKeyword(QLatin1String("otherwise"))),
1162  }
1163 
1164  queueToken(IF, to);
1165  queueToken(LPAREN, to);
1167  queueToken(RPAREN, to);
1168  queueToken(THEN, to);
1169  queueToken(LPAREN, to);
1172  queueToken(RPAREN, to);
1174  queueToken(ELSE, to);
1175  hasEncounteredAtLeastOneWhen = true;
1176  queueOnExit(onExitTokens, to);
1177  break;
1178  }
1179  case Otherwise:
1180  {
1181  if(!hasEncounteredAtLeastOneWhen)
1182  {
1183  error(QtXmlPatterns::tr("At least one %1-element must occur before %2.")
1184  .arg(formatKeyword(QLatin1String("when")),
1185  formatKeyword(QLatin1String("otherwise"))),
1187  }
1188  else if(hasHandledOtherwise)
1189  {
1190  error(QtXmlPatterns::tr("Only one %1-element can appear.")
1191  .arg(formatKeyword(QLatin1String("otherwise"))),
1193  }
1194 
1196  queueToken(LPAREN, to);
1197  insideSequenceConstructor(to, to);
1198  queueToken(RPAREN, to);
1199  hasHandledOtherwise = true;
1200  queueOnExit(onExitTokens, to);
1201  break;
1202  }
1203  default:
1205  }
1206  }
1207  else
1209  break;
1210  }
1212  {
1213  if(isXSLT())
1214  {
1215  switch(currentElementName())
1216  {
1217  case Choose:
1218  {
1219  if(!hasEncounteredAtLeastOneWhen)
1220  {
1221  error(QtXmlPatterns::tr("At least one %1-element must occur inside %2.")
1222  .arg(formatKeyword(QLatin1String("when")),
1223  formatKeyword(QLatin1String("choose"))),
1225  }
1226 
1227  if(!hasHandledOtherwise)
1228  queueEmptySequence(to);
1229  return;
1230  }
1231  case Otherwise:
1232  continue;
1233  default:
1235  }
1236  }
1237  else
1239  break;
1240  }
1242  /* Fallthrough. */
1244  continue;
1246  {
1247  /* We ignore regardless of what xml:space says, see step 4 in
1248  * 4.2 Stripping Whitespace from the Stylesheet. */
1249  if(isWhitespace())
1250  continue;
1251  /* Fallthrough. */
1252  }
1253  default:
1254  /* Fallthrough. */
1256  break;
1257  }
1258  }
1260 }
1261 
1263  const bool emptynessAllowed,
1264  TokenSource::Queue *const to,
1265  const QXmlStreamAttributes *const attsP,
1266  const bool queueEmptyOnEmpty)
1267 {
1269  const NodeName elementName(currentElementName());
1270  const QXmlStreamAttributes atts(attsP ? *attsP : m_currentAttributes);
1271 
1272  if(atts.hasAttribute(QLatin1String("select")))
1273  {
1274  queueExpression(atts.value(QLatin1String("select")).toString(), to);
1275 
1276  /* First, verify that we don't have a body. */
1277  if(skipSubTree(true))
1278  {
1279  error(QtXmlPatterns::tr("When attribute %1 is present on %2, a sequence "
1280  "constructor cannot be used.").arg(formatKeyword(QLatin1String("select")),
1281  formatKeyword(toString(elementName))),
1282  code);
1283  }
1284 
1285  return true;
1286  }
1287  else
1288  {
1290  if(!insideSequenceConstructor(to, true, queueEmptyOnEmpty) && !emptynessAllowed)
1291  {
1292  error(QtXmlPatterns::tr("Element %1 must have either a %2-attribute "
1293  "or a sequence constructor.").arg(formatKeyword(toString(elementName)),
1294  formatKeyword(QLatin1String("select"))),
1295  code);
1296 
1297  }
1298 
1299  return false;
1300  }
1301 }
1302 
1304  const bool emptynessAllowed,
1305  TokenSource::Queue *const to,
1306  const bool selectOnlyFirst)
1307 {
1309  queueToken(Token(NCNAME, QLatin1String("generic-string-join")), to);
1310  queueToken(LPAREN, to);
1311 
1312  /* We have to read the attribute before calling
1313  * queueSelectOrSequenceConstructor(), since it advances the reader. */
1314  const bool hasSeparator = m_currentAttributes.hasAttribute(QLatin1String("separator"));
1315  const QString separatorAVT(m_currentAttributes.value(QLatin1String("separator")).toString());
1316 
1317  queueToken(LPAREN, to);
1318  const bool viaSelectAttribute = queueSelectOrSequenceConstructor(code, emptynessAllowed, to);
1319  queueToken(RPAREN, to);
1320 
1321  if(selectOnlyFirst)
1322  {
1323  queueToken(LBRACKET, to);
1325  queueToken(RBRACKET, to);
1326  }
1327 
1328  queueToken(COMMA, to);
1329 
1330  if(hasSeparator)
1331  queueAVT(separatorAVT, to);
1332  else
1333  {
1334  /* The default value depends on whether the value is from @select, or from
1335  * the sequence constructor. */
1336  queueToken(Token(STRING_LITERAL, viaSelectAttribute ? QString(QLatin1Char(' '))
1337  : QString()),
1338  to);
1339  }
1340 
1341  queueToken(RPAREN, to);
1342 }
1343 
1345  bool &hasWrittenExpression,
1346  TokenSource::Queue *const to)
1347 {
1348  if(!chars.isEmpty())
1349  {
1350  commencingExpression(hasWrittenExpression, to);
1351  queueToken(TEXT, to);
1352  queueToken(CURLY_LBRACE, to);
1353  queueToken(Token(STRING_LITERAL, chars), to);
1354  queueToken(CURLY_RBRACE, to);
1355  chars.clear();
1356  }
1357 }
1358 
1360  TokenSource::Queue *const to)
1361 {
1363 
1364  if(variableType == VariableInstruction)
1365  {
1366  queueToken(LET, to);
1367  queueToken(INTERNAL, to);
1368  }
1369  else if(variableType == VariableDeclaration || variableType == GlobalParameter)
1370  {
1371  queueToken(DECLARE, to);
1372  queueToken(VARIABLE, to);
1373  queueToken(INTERNAL, to);
1374  }
1375 
1376  queueToken(DOLLAR, to);
1377 
1378  queueExpression(readAttribute(QLatin1String("name")), to, false);
1379 
1380  const bool hasAs = m_currentAttributes.hasAttribute(QLatin1String("as"));
1381  if(hasAs)
1382  {
1383  queueToken(AS, to);
1385  }
1386 
1387  if(variableType == FunctionParameter)
1388  {
1390  return;
1391  }
1392 
1393  /* We must do this here, because queueSelectOrSequenceConstructor()
1394  * advances the reader. */
1395  const bool hasSelect = hasAttribute(QLatin1String("select"));
1396  const bool isRequired = hasAttribute(QLatin1String("required")) ? attributeYesNo(QLatin1String("required")) : false;
1397 
1398  TokenSource::Queue storage;
1399  queueSelectOrSequenceConstructor(ReportContext::XTSE0620, true, &storage, 0, false);
1400 
1401  /* XSL-T has some wicked rules, see
1402  * 9.3 Values of Variables and Parameters. */
1403 
1404  const bool hasQueuedContent = !storage.isEmpty();
1405 
1406  /* The syntax for global parameters is:
1407  *
1408  * declare variable $var external := 'defaultValue';
1409  */
1410  if(variableType == GlobalParameter)
1411  queueToken(EXTERNAL, to);
1412 
1413  if(isRequired)
1414  {
1415  if(hasQueuedContent)
1416  {
1417  error(QtXmlPatterns::tr("When a parameter is required, a default value "
1418  "cannot be supplied through a %1-attribute or "
1419  "a sequence constructor.").arg(formatKeyword(QLatin1String("select"))),
1421  }
1422  }
1423  else
1424  {
1425  if(hasQueuedContent)
1426  {
1427  queueToken(ASSIGN, to);
1428 
1429  if(!hasSelect && !hasAs && !hasQueuedContent)
1431  else if(hasAs || hasSelect)
1432  queueToken(LPAREN, to);
1433  else
1434  {
1435  queueToken(DOCUMENT, to);
1436  queueToken(INTERNAL, to);
1437  queueToken(CURLY_LBRACE, to);
1438  }
1439  }
1440  else
1441  {
1442  if(!hasAs)
1443  {
1444  queueToken(ASSIGN, to);
1446  }
1447  else if(variableType == VariableDeclaration || variableType == VariableInstruction)
1448  {
1449  queueToken(ASSIGN, to);
1450  queueEmptySequence(to);
1451  }
1452  }
1453 
1454  /* storage has tokens if hasSelect or hasQueuedContent is true. */
1455  if(hasSelect | hasQueuedContent)
1456  *to += storage;
1457 
1458  if(hasQueuedContent)
1459  {
1460  if(!hasSelect && !hasAs && !hasQueuedContent)
1462  else if(hasAs || hasSelect)
1463  queueToken(RPAREN, to);
1464  else
1465  queueToken(CURLY_RBRACE, to);
1466  }
1467  }
1468 
1469  if(variableType == VariableInstruction)
1470  queueToken(RETURN, to);
1471  else if(variableType == VariableDeclaration || variableType == GlobalParameter)
1472  queueToken(SEMI_COLON, to);
1473 }
1474 
1476 {
1477  queueToken(CURRENT, to);
1478  queueToken(CURLY_LBRACE, to);
1479 }
1480 
1482 {
1483  queueToken(CURLY_RBRACE, to);
1484 }
1485 
1487  QStack<Token> *const queueOnExit,
1488  const bool isDeclaration)
1489 {
1491  Q_ASSERT_X(isDeclaration || queueOnExit,
1492  Q_FUNC_INFO,
1493  "If isDeclaration is false, queueOnExit must be passed.");
1494 
1496 
1497  for(int i = 0; i < nss.count(); ++i)
1498  {
1499  const QXmlStreamNamespaceDeclaration &at = nss.at(i);
1500  queueToken(DECLARE, to);
1501  queueToken(NAMESPACE, to);
1502  queueToken(Token(NCNAME, at.prefix().toString()), to);
1503  queueToken(G_EQ, to);
1505 
1506  if(isDeclaration)
1507  {
1508  queueToken(INTERNAL, to);
1509  queueToken(SEMI_COLON, to);
1510  }
1511  else
1512  {
1513  queueToken(CURLY_LBRACE, to);
1514  queueOnExit->push(CURLY_RBRACE);
1515  }
1516  }
1517 }
1518 
1520  const bool initialAdvance,
1521  const bool queueEmptyOnEmpty)
1522 {
1523  QStack<Token> onExitTokens;
1524  return insideSequenceConstructor(to, onExitTokens, initialAdvance, queueEmptyOnEmpty);
1525 }
1526 
1528  QStack<Token> &onExitTokens,
1529  const bool initialAdvance,
1530  const bool queueEmptyOnEmpty)
1531 {
1532  bool effectiveInitialAdvance = initialAdvance;
1533  bool hasWrittenExpression = false;
1534 
1535  /* Buffer which all text nodes, that might be split up by comments,
1536  * processing instructions and CDATA sections, are appended to. */
1537  QString characters;
1538 
1539  while(!atEnd())
1540  {
1541  if(effectiveInitialAdvance)
1542  readNext();
1543  else
1544  effectiveInitialAdvance = true;
1545 
1546  switch(tokenType())
1547  {
1549  {
1550  queueTextConstructor(characters, hasWrittenExpression, to);
1551  handleXMLBase(to, &onExitTokens);
1552 
1554 
1555  commencingExpression(hasWrittenExpression, to);
1556 
1557  if(isXSLT())
1558  {
1559  handleXSLTVersion(&m_tokenSource, &onExitTokens, true);
1561  validateElement();
1562 
1563  queueNamespaceDeclarations(to, &onExitTokens);
1564 
1565  switch(currentElementName())
1566  {
1567  case If:
1568  {
1569  queueToken(IF, to);
1570  queueToken(LPAREN, to);
1571 
1573  queueToken(RPAREN, to);
1574  queueToken(THEN, to);
1575 
1576  queueToken(LPAREN, to);
1579 
1580  break;
1581  }
1582  case Choose:
1583  {
1584  insideChoose(to);
1585  break;
1586  }
1587  case ValueOf:
1588  {
1589  /* We generate a computed text node constructor. */
1590  queueToken(TEXT, to);
1591  queueToken(CURLY_LBRACE, to);
1592 
1595  queueToken(CURLY_RBRACE, to);
1596  break;
1597  }
1598  case Sequence:
1599  {
1602  break;
1603  }
1604  case Text:
1605  {
1606  queueToken(TEXT, to);
1607  queueToken(CURLY_LBRACE, to);
1608 
1610  queueToken(CURLY_RBRACE, to);
1611  break;
1612  }
1613  case Variable:
1614  {
1616 
1617  /* We wrap the children in parantheses since we may
1618  * queue several expressions using the comma operator,
1619  * and in that case the let-binding is only in-scope
1620  * for the first expression. */
1621  queueToken(LPAREN, to);
1622 
1623  /* We don't want a comma outputted, we're expecting an
1624  * expression now. */
1625  hasWrittenExpression = false;
1626 
1627  onExitTokens.push(RPAREN);
1628 
1629  break;
1630  }
1631  case CallTemplate:
1632  {
1635  queueToken(LPAREN, to);
1637  queueToken(RPAREN, to);
1638  break;
1639  }
1640  case ForEach:
1641  {
1643  queueToken(MAP, to);
1645 
1646  TokenSource::Queue sorts;
1647  queueSorting(false, &sorts);
1648 
1649 
1650  if(sorts.isEmpty())
1651  {
1653  insideSequenceConstructor(to, false);
1654  endStorageOfCurrent(to);
1655  }
1656  else
1657  {
1658  queueToken(SORT, to);
1659  *to += sorts;
1660  queueToken(RETURN, to);
1662  insideSequenceConstructor(to, false);
1663  endStorageOfCurrent(to);
1664  queueToken(END_SORT, to);
1665  }
1666 
1667  break;
1668  }
1670  {
1671  queueToken(COMMENT, to);
1672  queueToken(INTERNAL, to);
1673  queueToken(CURLY_LBRACE, to);
1675  queueToken(CURLY_RBRACE, to);
1676  break;
1677  }
1678  case CopyOf:
1679  {
1681  // TODO
1682 
1684  break;
1685  else
1686  {
1687  error(QtXmlPatterns::tr("Element %1 cannot have children.").arg(formatKeyword(QLatin1String("copy-of"))),
1689  }
1690  break;
1691  }
1692  case AnalyzeString:
1693  {
1694  // TODO
1695  skipSubTree();
1696  break;
1697  }
1698  case ResultDocument:
1699  {
1700  // TODO
1703  break;
1704  }
1705  case Copy:
1706  {
1707  /* We translate:
1708  * <xsl:copy>expr</xsl:copy>
1709  * into:
1710  *
1711  * let $body := expr
1712  * return
1713  * if(self::element()) then
1714  * element internal {node-name()} {$body}
1715  * else if(self::document-node()) then
1716  * document internal {$body}
1717  * else (: This includes comments, processing-instructions,
1718  * attributes, and comments. :)
1719  * .
1720  *
1721  * TODO node identity is the same as the old node.
1722  * TODO namespace bindings are lost when elements are constructed
1723  */
1724 
1725  /* let $body := expr */
1726  queueToken(LET, to);
1727  queueToken(INTERNAL, to);
1728  queueToken(DOLLAR, to);
1729  queueToken(Token(NCNAME, QString(QLatin1Char('b'))), to); // TODO we need an internal name
1730  queueToken(ASSIGN, to);
1731  queueToken(LPAREN, to);
1733  /* Don't queue an empty sequence, we want the dot. */
1735  queueToken(RPAREN, to);
1736  queueToken(RETURN, to);
1737 
1738  /* if(self::element()) then */
1739  queueToken(IF, to);
1740  queueToken(LPAREN, to);
1741  queueToken(SELF, to);
1742  queueToken(COLONCOLON, to);
1743  queueToken(ELEMENT, to);
1744  queueToken(LPAREN, to);
1745  queueToken(RPAREN, to);
1746  queueToken(RPAREN, to);
1747  queueToken(THEN, to);
1748 
1749  /* element internal {node-name()} {$body} */
1750  queueToken(ELEMENT, to);
1751  queueToken(INTERNAL, to);
1752  queueToken(CURLY_LBRACE, to);
1753  queueToken(Token(NCNAME, QLatin1String("node-name")), to); // TODO what if the default ns changes?
1754  queueToken(LPAREN, to);
1755  queueToken(DOT, to);
1756  queueToken(RPAREN, to);
1757  queueToken(CURLY_RBRACE, to);
1758  queueToken(CURLY_LBRACE, to);
1759  queueToken(DOLLAR, to);
1760  queueToken(Token(NCNAME, QString(QLatin1Char('b'))), to); // TODO we need an internal name
1761  queueToken(CURLY_RBRACE, to);
1762 
1763  /* else if(self::document-node()) then */
1764  queueToken(ELSE, to);
1765  queueToken(IF, to);
1766  queueToken(LPAREN, to);
1767  queueToken(SELF, to);
1768  queueToken(COLONCOLON, to);
1770  queueToken(LPAREN, to);
1771  queueToken(RPAREN, to);
1772  queueToken(RPAREN, to);
1773  queueToken(THEN, to);
1774 
1775  /* document internal {$body} */
1776  queueToken(DOCUMENT, to);
1777  queueToken(INTERNAL, to);
1778  queueToken(CURLY_LBRACE, to);
1779  queueToken(DOLLAR, to);
1780  queueToken(Token(NCNAME, QString(QLatin1Char('b'))), to); // TODO we need an internal name
1781  queueToken(CURLY_RBRACE, to);
1782 
1783  /* else . */
1784  queueToken(ELSE, to);
1785  queueToken(DOT, to);
1786 
1787  break;
1788  }
1790  {
1792  queueToken(CURLY_LBRACE, to);
1793  queueAVT(readAttribute(QLatin1String("name")), to);
1794  queueToken(CURLY_RBRACE, to);
1795  queueToken(CURLY_LBRACE, to);
1797  queueToken(CURLY_RBRACE, to);
1798  break;
1799  }
1800  case Document:
1801  {
1803 
1804  // TODO base-URI
1805  queueToken(DOCUMENT, to);
1806  queueToken(INTERNAL, to);
1807  queueToken(CURLY_LBRACE, to);
1810  queueToken(CURLY_RBRACE, to);
1811  break;
1812  }
1813  case Element:
1814  {
1816 
1817  // TODO base-URI
1818  queueToken(ELEMENT, to);
1819  queueToken(INTERNAL, to);
1820 
1821  /* The name. */
1822  queueToken(CURLY_LBRACE, to);
1823  // TODO only strings allowed, not qname values.
1824  queueAVT(readAttribute(QLatin1String("name")), to);
1825  queueToken(CURLY_RBRACE, to);
1826 
1827  /* The sequence constructor. */
1828  queueToken(CURLY_LBRACE, to);
1831  queueToken(CURLY_RBRACE, to);
1832  break;
1833  }
1834  case Attribute:
1835  {
1837 
1838  // TODO base-URI
1839  queueToken(ATTRIBUTE, to);
1840  queueToken(INTERNAL, to);
1841 
1842  /* The name. */
1843  queueToken(CURLY_LBRACE, to);
1844  // TODO only strings allowed, not qname values.
1845  queueAVT(readAttribute(QLatin1String("name")), to);
1846  queueToken(CURLY_RBRACE, to);
1847 
1848  /* The sequence constructor. */
1849  queueToken(CURLY_LBRACE, to);
1851  true, to);
1852  queueToken(CURLY_RBRACE, to);
1853  break;
1854  }
1855  case Namespace:
1856  {
1857  queueToken(NAMESPACE, to);
1858 
1859  /* The name. */
1860  queueToken(CURLY_LBRACE, to);
1861  queueAVT(readAttribute(QLatin1String("name")), to);
1862  queueToken(CURLY_RBRACE, to);
1863 
1864  /* The sequence constructor. */
1865  queueToken(CURLY_LBRACE, to);
1867  false, to);
1868  queueToken(CURLY_RBRACE, to);
1869  break;
1870  }
1871  case PerformSort:
1872  {
1873  /* For:
1874  * <xsl:perform-sort select="$in">
1875  * <xsl:sort select="@key"/>
1876  * </xsl:perform-sort>
1877  *
1878  * we generate:
1879  *
1880  * $in map sort order by @key
1881  * return .
1882  * end_sort
1883  */
1884 
1885  /* In XQuery, the sort keys appear after the expression
1886  * supplying the initial sequence, while in
1887  * xsl:perform-sort, if a sequence constructor is used,
1888  * they appear in the opposite order. Hence, we need to
1889  * reorder it. */
1890 
1891  /* We store the attributes of xsl:perform-sort, before
1892  * queueSorting() advances the reader. */
1894 
1895  TokenSource::Queue sorts;
1896  queueSorting(true, &sorts);
1898  true,
1899  to,
1900  &atts);
1901  /* queueSelectOrSequenceConstructor() positions us on EndElement. */
1902  effectiveInitialAdvance = false;
1903  queueToken(MAP, to);
1904  queueToken(SORT, to);
1905  *to += sorts;
1906  queueToken(RETURN, to);
1907  queueToken(DOT, to);
1908  queueToken(END_SORT, to);
1909 
1910  break;
1911  }
1912  case Message:
1913  {
1914  // TODO
1915  queueEmptySequence(to);
1916  skipSubTree();
1917  break;
1918  }
1919  case ApplyTemplates:
1920  {
1921  if(hasAttribute(QLatin1String("select")))
1923  else
1924  {
1925  queueToken(CHILD, to);
1926  queueToken(COLONCOLON, to);
1927  queueToken(NODE, to);
1928  queueToken(LPAREN, to);
1929  queueToken(RPAREN, to);
1930  }
1931 
1932  bool hasMode = hasAttribute(QLatin1String("mode"));
1933  QString mode;
1934 
1935  if(hasMode)
1936  mode = readAttribute(QLatin1String("mode")).trimmed();
1937 
1939 
1940  TokenSource::Queue sorts;
1941  queueSorting(false, &sorts, true);
1942 
1943  if(!sorts.isEmpty())
1944  {
1945  queueToken(SORT, to);
1946  *to += sorts;
1947  queueToken(RETURN, to);
1948  }
1949 
1951 
1952  if(hasMode)
1953  {
1954  queueToken(MODE, to);
1955  queueToken(Token(mode.startsWith(QLatin1Char('#')) ? NCNAME : QNAME, mode), to);
1956  }
1957 
1958  queueToken(LPAREN, to);
1959  queueWithParams(ApplyTemplates, to, false);
1960  queueToken(RPAREN, to);
1961 
1962  if(!sorts.isEmpty())
1963  queueToken(END_SORT, to);
1964 
1965  break;
1966  }
1967  default:
1969  }
1970  continue;
1971  }
1972  else
1973  {
1974  handleXSLTVersion(&m_tokenSource, &onExitTokens, true);
1975  handleStandardAttributes(false);
1977 
1978  /* We're generating an element constructor. */
1979  queueNamespaceDeclarations(to, &onExitTokens); // TODO same in the isXSLT() branch
1980  queueToken(ELEMENT, to);
1981  queueToken(INTERNAL, to);
1983  queueToken(CURLY_LBRACE, to);
1984  const int len = m_currentAttributes.count();
1985 
1986  for(int i = 0; i < len; ++i)
1987  {
1989 
1990  /* We don't want to generate constructors for XSL-T attributes. */
1992  continue;
1993 
1994  queueToken(ATTRIBUTE, to);
1995  queueToken(INTERNAL, to);
1996 
1997  queueToken(Token(at.prefix().isEmpty() ? NCNAME : QNAME, at.qualifiedName().toString()), to);
1998  queueToken(CURLY_LBRACE, to);
1999  queueAVT(at.value().toString(), to);
2000  queueToken(CURLY_RBRACE, to);
2001  queueToken(COMMA, to);
2002  }
2003 
2007  continue;
2008  }
2009 
2011  break;
2012  }
2014  {
2015  queueTextConstructor(characters, hasWrittenExpression, to);
2016  leaveState();
2017 
2018  if(!hasWrittenExpression && queueEmptyOnEmpty)
2019  queueEmptySequence(to);
2020 
2021  queueOnExit(onExitTokens, to);
2022 
2023  if(isXSLT())
2024  {
2026 
2027  switch(currentElementName())
2028  {
2029  /* Fallthrough all these. */
2030  case When:
2031  case Choose:
2032  case ForEach:
2033  case Otherwise:
2034  case PerformSort:
2035  case Message:
2036  case ResultDocument:
2037  case Copy:
2038  case CallTemplate:
2039  case Text:
2040  case ValueOf:
2041  {
2042  hasWrittenExpression = true;
2043  break;
2044  }
2045  case If:
2046  {
2047  queueToken(RPAREN, to);
2048  queueToken(ELSE, to);
2049  queueEmptySequence(to);
2050  break;
2051  }
2052  case Function:
2053  {
2054  queueToken(CURLY_RBRACE, to);
2055  queueToken(SEMI_COLON, to);
2056  break;
2057  }
2058  case Template:
2059  {
2061  /* TODO, fallthrough to Function. */
2062  queueToken(CURLY_RBRACE, to);
2063  queueToken(SEMI_COLON, to);
2064  break;
2065  }
2066  default:
2067  ;
2068  }
2069  }
2070  else
2071  {
2072  /* We're closing a direct element constructor. */
2073  hasWrittenExpression = true;
2074  queueToken(CURLY_RBRACE, to);
2075  }
2076 
2077  return hasWrittenExpression;
2078  }
2080  /* Fallthrough. */
2082  /* We do nothing, we just ignore them. */
2083  continue;
2085  {
2086  if(whitespaceToSkip())
2087  continue;
2088  else
2089  {
2090  characters += text().toString();
2091  continue;
2092  }
2093  }
2094  default:
2095  ;
2096  }
2097  }
2098 
2099  leaveState();
2100  return hasWrittenExpression;
2101 }
2102 
2104 {
2105  Q_ASSERT(isXSLT());
2108 
2109  const NodeName name = currentElementName();
2110  return name == Stylesheet || name == Transform;
2111 }
2112 
2114 {
2115  Q_ASSERT(isXSLT());
2117  const NodeName name(currentElementName());
2118 
2119  if(skipSubTree())
2120  {
2121  error(QtXmlPatterns::tr("Element %1 cannot have a sequence constructor.")
2122  .arg(formatKeyword(toString(name))),
2123  code);
2124  }
2125 }
2126 
2128  TokenSource::Queue *const to,
2129  const bool initialAdvance)
2130 {
2131  Q_ASSERT(parentName == ApplyTemplates || parentName == CallTemplate);
2132 
2133  bool effectiveInitialAdvance = initialAdvance;
2134  bool hasQueuedParam = false;
2135 
2136  while(!atEnd())
2137  {
2138  if(effectiveInitialAdvance)
2139  readNext();
2140  else
2141  effectiveInitialAdvance = true;
2142 
2143  switch(tokenType())
2144  {
2146  {
2147  if(hasQueuedParam)
2148  queueToken(COMMA, to);
2149 
2150  if(isXSLT() && isElement(WithParam))
2151  {
2152  if(hasAttribute(QLatin1String("tunnel")) && attributeYesNo(QLatin1String("tunnel")))
2153  queueToken(TUNNEL, to);
2154 
2156  hasQueuedParam = true;
2157  continue;
2158  }
2159  else
2161  }
2163  {
2164  if(isElement(parentName))
2165  return;
2166  else
2167  continue;
2168  }
2170  /* Fallthrough. */
2172  continue;
2174  if(whitespaceToSkip())
2175  continue;
2176  else
2177  return;
2178  default:
2180  }
2181  }
2183 }
2184 
2186  TokenSource::Queue *const to)
2187 {
2188  bool hasQueuedParam = false;
2189 
2191 
2192  while(!atEnd())
2193  {
2194  switch(readNext())
2195  {
2197  {
2198  if(isXSLT() && isElement(Param))
2199  {
2200  if(hasQueuedParam)
2201  queueToken(COMMA, to);
2202 
2203  validateElement();
2204 
2205  if(parentName == Function && m_currentAttributes.hasAttribute(QLatin1String("select")))
2206  {
2207  error(QtXmlPatterns::tr("The attribute %1 cannot appear on %2, when it is a child of %3.")
2208  .arg(formatKeyword(QLatin1String("select")),
2209  formatKeyword(QLatin1String("param")),
2210  formatKeyword(QLatin1String("function"))),
2212  }
2213 
2214  if(parentName == Function && m_currentAttributes.hasAttribute(QLatin1String("required")))
2215  {
2216  error(QtXmlPatterns::tr("The attribute %1 cannot appear on %2, when it is a child of %3.")
2217  .arg(formatKeyword(QLatin1String("required")),
2218  formatKeyword(QLatin1String("param")),
2219  formatKeyword(QLatin1String("function"))),
2221  }
2222 
2223  const bool hasTunnel = m_currentAttributes.hasAttribute(QLatin1String("tunnel"));
2224  const bool isTunnel = hasTunnel ? attributeYesNo(QLatin1String("tunnel")) : false;
2225 
2226  if(isTunnel)
2227  {
2228  if(parentName == Function)
2229  {
2230  /* See W3C public report 5650: http://www.w3.org/Bugs/Public/show_bug.cgi?id=5650 */
2231  error(QtXmlPatterns::tr("A parameter in a function cannot be declared to be a tunnel."),
2233  }
2234  else
2235  queueToken(TUNNEL, to);
2236  }
2237 
2238  hasQueuedParam = true;
2240  continue;
2241  }
2242  else
2243  return;
2244  }
2246  {
2247  if(whitespaceToSkip())
2248  continue;
2249  /* Fallthrough. */
2250  }
2252  return;
2253  default:
2254  ;
2255  }
2256  }
2257 }
2258 
2259 bool XSLTTokenizer::skipSubTree(const bool exitOnContent)
2260 {
2261  bool hasContent = false;
2262  int depth = 0;
2263 
2264  while(!atEnd())
2265  {
2266  switch(readNext())
2267  {
2269  {
2270  if(whitespaceToSkip())
2271  continue;
2272  else
2273  {
2274  hasContent = true;
2275  if(exitOnContent)
2276  return true;
2277 
2278  break;
2279  }
2280  }
2282  {
2283  hasContent = true;
2284  if(exitOnContent)
2285  return true;
2286 
2287  ++depth;
2288  break;
2289  }
2291  {
2292  --depth;
2293  break;
2294  }
2295  default:
2296  continue;
2297  }
2298 
2299  if(depth == -1)
2300  return hasContent;
2301  }
2302 
2304  return hasContent;
2305 }
2306 
2308 {
2309  Q_ASSERT(isXSLT());
2311 
2312  skipSubTree();
2314 }
2315 
2317 {
2318  while(!atEnd())
2319  {
2320  switch(readNext())
2321  {
2323  {
2324  if(isXSLT() && isElement(AttributeSet))
2325  {
2326  // TODO
2327  skipSubTree();
2328  }
2329  else
2331  }
2333  return;
2335  /* Fallthrough. */
2337  continue;
2339  if(whitespaceToSkip())
2340  continue;
2341  /* Fallthrough. */
2342  default:
2344  }
2345  }
2347 }
2348 
2350 {
2351  while(!atEnd())
2352  {
2353  switch(readNext())
2354  {
2356  {
2357  if(isXSLT())
2358  {
2360  handleXSLTVersion(0, 0, true, 0, false);
2361  validateElement();
2362 
2363  /* Handle the various declarations. */
2364  switch(currentElementName())
2365  {
2366  case Template:
2367  insideTemplate();
2368  break;
2369  case Function:
2370  insideFunction();
2371  break;
2372  case Variable:
2374  break;
2375  case Param:
2377  break;
2378  case ImportSchema:
2379  {
2380  error(QtXmlPatterns::tr("This processor is not Schema-aware and "
2381  "therefore %1 cannot be used.").arg(formatKeyword(toString(ImportSchema))),
2383  break;
2384  }
2385  case Output:
2386  {
2387  // TODO
2388  skipSubTree();
2389  break;
2390  }
2391  case StripSpace:
2392  /* Fallthrough. */
2393  case PreserveSpace:
2394  {
2395  // TODO @elements
2396  skipSubTree(true);
2397  readNext();
2398 
2399  if(!isEndElement())
2401  break;
2402  }
2403  case Include:
2404  {
2405  // TODO
2406  if(skipSubTree(true))
2408  break;
2409  }
2410  case Import:
2411  {
2412  // TODO
2413  if(skipSubTree(true))
2415  break;
2416  }
2417  case Key:
2418  {
2419  // TODO
2420  skipSubTree();
2421  break;
2422  }
2423  case AttributeSet:
2425  break;
2426  default:
2429  }
2430  }
2431  else
2432  {
2433  /* We have a user-defined data element. See section 3.6.2. */
2434 
2435  if(namespaceUri().isEmpty())
2436  {
2437  error(QtXmlPatterns::tr("Top level stylesheet elements must be "
2438  "in a non-null namespace, which %1 isn't.").arg(formatKeyword(name())),
2440  }
2441  else
2442  skipSubTree();
2443  }
2444  break;
2445  }
2447  {
2448  /* Regardless of xml:space, we skip whitespace, see step 4 in
2449  * 4.2 Stripping Whitespace from the Stylesheet. */
2450  if(isWhitespace())
2451  continue;
2452 
2454  break;
2455  }
2457  {
2458  if(isXSLT())
2459  leaveState();
2460 
2461  break;
2462  }
2463  default:
2464  ;
2465  }
2466  }
2468 }
2469 
2471  const QString &isTrue,
2472  const QString &isFalse,
2473  const QXmlStreamAttributes *const attsP) const
2474 {
2475  const QXmlStreamAttributes atts(attsP ? *attsP : m_currentAttributes);
2476  Q_ASSERT(atts.hasAttribute(localName));
2477  const QString value(atts.value(localName).toString());
2478 
2479  if(value == isTrue)
2480  return true;
2481  else if(value == isFalse)
2482  return false;
2483  else
2484  {
2485  error(QtXmlPatterns::tr("The value for attribute %1 on element %2 must either "
2486  "be %3 or %4, not %5.").arg(formatKeyword(localName),
2487  formatKeyword(name()),
2488  formatData(isTrue),
2489  formatData(isFalse),
2490  formatData(value)),
2492  /* Silences a compiler warning. */
2493  return false;
2494  }
2495 }
2496 
2498  const QXmlStreamAttribute &attr) const
2499 {
2500  const QString value(attr.value().toString().trimmed());
2501 
2502  if(alternatives.contains(value))
2503  return alternatives[value];
2504 
2505  error(QtXmlPatterns::tr("Attribute %1 cannot have the value %2.")
2506  .arg(formatKeyword(attr.name().toString()),
2507  formatData(attr.value().toString())),
2509  return 0; /* Silence compiler warning. */
2510 }
2511 
2512 bool XSLTTokenizer::attributeYesNo(const QString &localName) const
2513 {
2514  return readToggleAttribute(localName, QLatin1String("yes"), QLatin1String("no"));
2515 }
2516 
2517 void XSLTTokenizer::queueSorting(const bool oneSortRequired,
2518  TokenSource::Queue *const to,
2519  const bool speciallyTreatWhitespace)
2520 {
2522 
2523  const NodeName elementName(currentElementName());
2524  bool hasQueuedOneSort = false;
2525 
2526  while(!atEnd())
2527  {
2528  switch(readNext())
2529  {
2531  {
2532  /* Let's say we have no sequence constructor, but only
2533  * ignorable space. In that case we will actually loop
2534  * infinitely if we don't have this check. */
2535  if(isXSLT())
2536  {
2537  switch(currentElementName())
2538  {
2539  case PerformSort:
2540  /* Fallthrough. */
2541  case ForEach:
2542  /* Fallthrough. */
2543  case ApplyTemplates:
2544  return;
2545  default:
2546  ;
2547  }
2548  }
2549  continue;
2550  }
2552  {
2553  if(isXSLT() && isElement(Sort))
2554  {
2555  if(hasQueuedOneSort)
2556  queueToken(COMMA, to);
2557 
2558  /* sorts are by default stable. */
2559  if(hasAttribute(QLatin1String("stable")))
2560  {
2561  if(hasQueuedOneSort)
2562  {
2563  error(QtXmlPatterns::tr("The attribute %1 can only appear on "
2564  "the first %2 element.").arg(formatKeyword(QLatin1String("stable")),
2565  formatKeyword(QLatin1String("sort"))),
2567  }
2568 
2569  if(attributeYesNo(QLatin1String("stable")))
2570  queueToken(STABLE, to);
2571  }
2572 
2573  if(!hasQueuedOneSort)
2574  {
2575  queueToken(ORDER, to);
2576  queueToken(BY, to);
2577  }
2578 
2579  /* We store a copy such that we can use them after
2580  * queueSelectOrSequenceConstructor() advances the reader. */
2582 
2583  const int before = to->count();
2584 
2585  // TODO This doesn't work as is. @data-type can be an AVT.
2586  if(atts.hasAttribute(QLatin1String("data-type")))
2587  {
2588  if(readToggleAttribute(QLatin1String("data-type"),
2589  QLatin1String("text"),
2590  QLatin1String("number"),
2591  &atts))
2592  queueToken(Token(NCNAME, QLatin1String("string")), to);
2593  else
2594  queueToken(Token(NCNAME, QLatin1String("number")), to);
2595  }
2596  /* We queue these parantheses for the sake of the function
2597  * call for attribute data-type. In the case we don't have
2598  * such an attribute, the parantheses are just redundant. */
2599  queueToken(LPAREN, to);
2601  true,
2602  to,
2603  0,
2604  false);
2605  /* If neither a select attribute or a sequence constructor is supplied,
2606  * we're supposed to use the context item. */
2607  queueToken(RPAREN, to);
2608  if(before == to->count())
2609  queueToken(DOT, to);
2610 
2611  // TODO case-order
2612  // TODO lang
2613 
2614  // TODO This doesn't work as is. @order can be an AVT, and so can case-order and lang.
2615  if(atts.hasAttribute(QLatin1String("order")) && readToggleAttribute(QLatin1String("order"),
2616  QLatin1String("descending"),
2617  QLatin1String("ascending"),
2618  &atts))
2619  {
2620  queueToken(DESCENDING, to);
2621  }
2622  else
2623  {
2624  /* This is the default. */
2625  queueToken(ASCENDING, to);
2626  }
2627 
2628  if(atts.hasAttribute(QLatin1String("collation")))
2629  {
2630  queueToken(INTERNAL, to);
2631  queueToken(COLLATION, to);
2632  queueAVT(atts.value(QLatin1String("collation")).toString(), to);
2633  }
2634 
2635  hasQueuedOneSort = true;
2636  continue;
2637  }
2638  else
2639  break;
2640  }
2642  {
2643  if(speciallyTreatWhitespace && isWhitespace())
2644  continue;
2645 
2647  continue;
2648 
2649  /* We have an instruction which is a text node, we're done. */
2650  break;
2651  }
2653  /* Fallthrough. */
2655  continue;
2656  default:
2658 
2659  };
2660  if(oneSortRequired && !hasQueuedOneSort)
2661  {
2662  error(QtXmlPatterns::tr("At least one %1 element must appear as child of %2.")
2663  .arg(formatKeyword(QLatin1String("sort")), formatKeyword(toString(elementName))),
2665  }
2666  else
2667  return;
2668  }
2670 }
2671 
2673 {
2679  const QString expectedType(hasAttribute(QLatin1String("as")) ? readAttribute(QLatin1String("as")): QString());
2680 
2681  if(hasAttribute(QLatin1String("override")))
2682  {
2683  /* We currently have no external functions, so we don't pass it on currently. */
2684  attributeYesNo(QLatin1String("override"));
2685  }
2686 
2688 
2690 
2691  if(!expectedType.isNull())
2692  {
2694  queueSequenceType(expectedType);
2695  }
2696 
2697  QStack<Token> onExitTokens;
2698  handleXMLBase(&m_tokenSource, &onExitTokens, true, &m_currentAttributes);
2699  handleXSLTVersion(&m_tokenSource, &onExitTokens, true);
2701 
2703  insideSequenceConstructor(&m_tokenSource, onExitTokens, false);
2704  /* We don't queue CURLY_RBRACE, because it's done in
2705  * insideSequenceConstructor(). */
2706 }
2707 
2709 {
2710  YYLTYPE retval;
2711  retval.first_line = lineNumber();
2712  retval.first_column = columnNumber();
2713  return retval;
2714 }
2715 
2717 
Error error() const
Returns the type of the current error, or NoError if no error occurred.
QBool contains(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.h:904
void warning(const QString &message) const
Convenience function for calling ReportContext::warning().
QString toString() const
Returns a copy of the string reference as a QString object.
Definition: qstring.cpp:8653
void queueOnExit(QStack< Token > &source, TokenSource::Queue *const destination)
Sends the tokens in source to destination.
virtual bool isAnyAttributeAllowed() const
Returns true, if any attribute is allowed on the element currently being validated.
bool insideSequenceConstructor(TokenSource::Queue *const to, const bool initialAdvance=true, const bool queueEmptyOnEmpty=true)
TokenSource::Queue m_tokenSource
QString Q_AUTOTEST_EXPORT escape(const QString &input)
Similar to Qt::escape(), but also escapes apostrophes and quotes, such that the result is suitable as...
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
Represents a declared variable. Only used at the compilation stage.
static AtomicValue::Ptr fromLexical(const QString &strNumeric)
Definition: qdecimal.cpp:64
const QChar at(int i) const
Returns the character at the given index position in the string.
Definition: qstring.h:698
qint64 lineNumber() const
Returns the current line number, starting with 1.
QString formatKeyword(const QString &keyword)
int count(const T &t) const
Returns the number of occurrences of value in the vector.
Definition: qvector.h:742
void queueSimpleContentConstructor(const ReportContext::ErrorCode code, const bool emptynessAllowed, TokenSource::Queue *const to, const bool selectOnlyFirst=false)
QString formatType(const NamePool::Ptr &np, const T &type)
Formats ItemType and SequenceType.
#define at(className, varName)
const Tokenizer::Token m_token
static qreal position(QGraphicsObject *item, QDeclarativeAnchorLine::AnchorLine anchorLine)
virtual Tokenizer::Token nextToken(YYLTYPE *const sourceLocator)
QStringRef value() const
Returns the attribute&#39;s value.
Definition: qxmlstream.h:156
bool isEndElement() const
Returns true if tokenType() equals EndElement ; otherwise returns false.
Definition: qxmlstream.h:338
void queueWithParams(const NodeName parentName, TokenSource::Queue *const to, const bool initialAdvance=true)
The QExplicitlySharedDataPointer class represents a pointer to an explicitly shared object...
Definition: qshareddata.h:136
void startStorageOfCurrent(TokenSource::Queue *const to)
void handleStandardAttributes(const bool isXSLTElement)
Handles xml:space and standard attributes.
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition: qstring.cpp:3734
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
QStringRef name() const
Returns the local name of a StartElement, EndElement, or an EntityReference.
int count(const T &t) const
Returns the number of occurrences of value in the list.
Definition: qlist.h:891
const NamePool::Ptr m_namePool
static ElementDescription< XSLTTokenLookup >::Hash createElementDescriptions()
int readAlternativeAttribute(const QHash< QString, int > &alternatives, const QXmlStreamAttribute &attr) const
bool atEnd() const
Returns true if the reader has read until the end of the XML document, or if an error() has occurred ...
Definition: qxmlstream.cpp:590
The QUrl class provides a convenient interface for working with URLs.
Definition: qurl.h:61
The QString class provides a Unicode character string.
Definition: qstring.h:83
void handleXSLTVersion(TokenSource::Queue *const to, QStack< Token > *const queueOnExit, const bool isXSLTElement, const QXmlStreamAttributes *atts=0, const bool generateCode=true, const bool setGlobalVersion=false)
The QHash class is a template class that provides a hash-table-based dictionary.
Definition: qdatastream.h:66
XSLTTokenizer(QIODevice *const queryDevice, const QUrl &location, const ReportContext::Ptr &context, const NamePool::Ptr &np)
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
bool hasAttribute(const QString &namespaceURI, const QString &localName) const
Returns true if the current element has an attribute whose name is namespaceURI and local name is loc...
xsDouble xsDecimal
bool contains(const Key &key) const
Returns true if the hash contains an item with the key; otherwise returns false.
Definition: qhash.h:872
QStringRef qualifiedName() const
Returns the attribute&#39;s qualified name.
Definition: qxmlstream.h:150
bool hasAttribute(const QString &qualifiedName) const
Definition: qxmlstream.h:181
void endStorageOfCurrent(TokenSource::Queue *const to)
void reserve(int size)
Ensures that the QHash&#39;s internal hash table consists of at least size buckets.
Definition: qhash.h:846
bool isEmpty() const
Returns true if the list contains no items; otherwise returns false.
Definition: qlist.h:152
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition: qhash.h:753
void queueParams(const NodeName parentName, TokenSource::Queue *const to)
QStringRef value(const QString &namespaceUri, const QString &name) const
Returns the value of the attribute name in the namespace described with namespaceUri, or an empty string reference if the attribute is not defined.
const QLatin1String XSLT("http://www.w3.org/1999/XSL/Transform")
T pop()
Removes the top item from the stack and returns it.
Definition: qstack.h:67
The QXmlStreamAttribute class represents a single XML attribute.
Definition: qxmlstream.h:135
QStringRef namespaceUri() const
Returns the namespaceUri of a StartElement or EndElement.
void queueToken(const Token &token, TokenSource::Queue *const ts)
TokenType tokenType() const
Returns the type of the current token.
Definition: qxmlstream.cpp:656
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
A TokenSource which contains one Tokenizer::Token.
QString trimmed() const Q_REQUIRED_RESULT
Returns a string that has whitespace removed from the start and the end.
Definition: qstring.cpp:4506
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
void queueSorting(const bool oneSortRequired, TokenSource::Queue *const to, const bool speciallyTreatWhitespace=false)
bool hasError() const
Returns true if an error has occurred, otherwise false.
Definition: qxmlstream.h:396
void queueTextConstructor(QString &chars, bool &hasWrittenExpression, TokenSource::Queue *const to)
const QLatin1String XML("http://www.w3.org/XML/1998/namespace")
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
void validateElement(const LookupKey name) const
The namespace for the internal API of QtXmlPatterns.
bool isEmpty() const
Returns true if the string reference has no characters; otherwise returns false.
Definition: qstring.h:1169
void queueNamespaceDeclarations(TokenSource::Queue *const ts, QStack< Token > *const target, const bool isDeclaration=false)
const_iterator insert(const T &value)
Definition: qset.h:179
virtual Token nextToken(YYLTYPE *const sourceLocator)
QStack< ProcessMode > m_processingMode
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal...
Definition: qstring.h:654
T & head()
Returns a reference to the queue&#39;s head item.
Definition: qqueue.h:62
A hand-written tokenizer which tokenizes XQuery 1.0 & XPath 2.0, and delivers tokens to the Bison gen...
QStringRef namespaceUri() const
Returns the namespaceUri.
Definition: qxmlstream.h:216
bool skipSubTree(const bool exitOnContent=false)
static QChar fromLatin1(char c)
Converts the Latin-1 character c to its equivalent QChar.
Definition: qchar.h:378
int count() const
Definition: qset.h:178
QStringRef prefix() const
Returns the prefix.
Definition: qxmlstream.h:215
void queueSequenceType(const QString &expr)
bool queueSelectOrSequenceConstructor(const ReportContext::ErrorCode code, const bool emptynessAllowed, TokenSource::Queue *const to, const QXmlStreamAttributes *const atts=0, const bool queueEmptyOnEmpty=true)
void handleXMLBase(TokenSource::Queue *const to, QStack< Token > *const queueOnExit, const bool isInstruction=true, const QXmlStreamAttributes *atts=0)
Generates code for reflecting xml:base attributes.
QStringRef name() const
Returns the attribute&#39;s local name.
Definition: qxmlstream.h:149
YYLTYPE currentSourceLocator() const
The State element defines configurations of objects and properties.
static QString formatData(const QString &data)
void hasWrittenExpression(bool &beacon)
Base class for tokenizers that reads XML formats. This is XSLTTokenizer, and the W3C XML Schema parse...
const QHash< QString, int > m_validationAlternatives
void push(const T &t)
Adds element t to the top of the stack.
Definition: qstack.h:60
void queueVariableDeclaration(const VariableType variableType, TokenSource::Queue *const to)
void queueAVT(const QString &expr, TokenSource::Queue *const to)
void insideChoose(TokenSource::Queue *const to)
The QStringRef class provides a thin wrapper around QString substrings.
Definition: qstring.h:1099
const T & at(int i) const
Returns the item at index position i in the vector.
Definition: qvector.h:350
QStringRef qualifiedName() const
Returns the qualified name of a StartElement or EndElement;.
The QXmlStreamNamespaceDeclaration class represents a namespace declaration.
Definition: qxmlstream.h:204
bool isNull() const
Returns true if this string is null; otherwise returns false.
Definition: qstring.h:505
XSLTTokenLookup ::NodeName currentElementName() const
void enqueue(const T &t)
Adds value t to the tail of the queue.
Definition: qqueue.h:60
#define Q_ASSERT_X(cond, where, what)
Definition: qglobal.h:1837
QString arg(qlonglong a, int fieldwidth=0, int base=10, const QChar &fillChar=QLatin1Char(' ')) const Q_REQUIRED_RESULT
Definition: qstring.cpp:7186
Contains functions used for formatting arguments, such as keywords and paths, in translated strings...
Contains data related to a template.
Definition: qtemplate_p.h:84
Base class for all numeric values.
void pushState(const State nextState)
virtual void setCompatModeEnabled(const bool newVal)=0
The QXmlStreamAttributes class represents a vector of QXmlStreamAttribute.
Definition: qxmlstream.h:169
void clear()
Clears the contents of the string and makes it empty.
Definition: qstring.h:723
static QHash< QString, int > createValidationAlternatives()
qint64 columnNumber() const
Returns the current column number, starting with 0.
static QTestResult::TestLocation location
Definition: qtestresult.cpp:63
void handleValidationAttributes(const bool isLRE) const
QStringRef prefix() const
Returns the attribute&#39;s namespace prefix.
Definition: qxmlstream.h:151
QXmlStreamNamespaceDeclarations namespaceDeclarations() const
If the state() is StartElement , this function returns the element&#39;s namespace declarations.
const StaticContext::Ptr staticContext
virtual void resumeTokenizationFrom(const int position)
static QString toString(NodeName token)
QString readAttribute(const QString &localName, const QString &namespaceURI=QString()) const
Returns the value for attribute by name name.
static const AtomicType::Ptr xsDecimal
QSet< typename TokenLookupClass::NodeName > requiredAttributes
int count(const Key &key) const
Returns the number of items associated with the key.
Definition: qhash.h:719
void queueExpression(const QString &expr, TokenSource::Queue *const to, const bool wrapWithParantheses=true)
bool isEmpty() const
Returns true if the vector has size 0; otherwise returns false.
Definition: qvector.h:139
QStringList split(const QString &sep, SplitBehavior behavior=KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const Q_REQUIRED_RESULT
Splits the string into substrings wherever sep occurs, and returns the list of those strings...
Definition: qstring.cpp:6526
Carries meta data for xsl:with-param as encountered in template callsites such as xsl:call-template a...
Definition: qwithparam_p.h:75
QSet< typename TokenLookupClass::NodeName > optionalAttributes
A structure that lists the optional and required attributes of an element. Used with MaintainingReade...
void commencingExpression(bool &hasWrittenExpression, TokenSource::Queue *const to)
bool isNull() const
Returns true if string() returns a null pointer or a pointer to a null string; otherwise returns true...
Definition: qstring.h:1170
T dequeue()
Removes the head item in the queue and returns it.
Definition: qqueue.h:61
QStringRef text() const
Returns the text of Characters , Comment , DTD , or EntityReference.
QString errorString() const
Returns the error message that was set with raiseError().
Base class for all tokenizers.
Definition: qtokenizer_p.h:155
The QIODevice class is the base interface class of all I/O devices in Qt.
Definition: qiodevice.h:66
Flags
bool readToggleAttribute(const QString &attributeName, const QString &isTrue, const QString &isFalse, const QXmlStreamAttributes *const atts=0) const
const QUrl & queryURI() const
Definition: qtokenizer_p.h:187
void skipBodyOfParam(const ReportContext::ErrorCode code)
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
ParserContext::Ptr m_parseInfo
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
QXmlStreamAttributes attributes() const
Returns the attributes of a StartElement.
bool attributeYesNo(const QString &localName) const
static NodeName toToken(const QString &value)
virtual void setParserContext(const ParserContext::Ptr &parseInfo)
bool isElement(const NodeName &name) const
static QSet< NodeName > createStandardAttributes()
void queueEmptySequence(TokenSource::Queue *const to)
Implements xsl:call-template.
T & top()
Returns a reference to the stack&#39;s top item.
Definition: qstack.h:72
#define Q_FUNC_INFO
Definition: qglobal.h:1871
void unexpectedContent(const ReportContext::ErrorCode code=ReportContext::XTSE0010) const
void reserve(int size)
Definition: qset.h:241
QStringRef namespaceUri() const
Returns the attribute&#39;s resolved namespaceUri, or an empty string reference if the attribute does not...
Definition: qxmlstream.h:148