2004-06-25 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / Commons.Xml.Relaxng / Commons.Xml.Relaxng / RelaxngReader.cs
1 //\r
2 // Commons.Xml.Relaxng.RelaxngReader.cs\r
3 //\r
4 // Author:\r
5 //      Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>\r
6 //\r
7 // 2003 Atsushi Enomoto "No rights reserved."\r
8 //\r
9 // Copyright (c) 2004 Novell Inc.\r
10 // All rights reserved\r
11 //\r
12
13 //
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
21 // 
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
24 // 
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 //
33 \r
34 using System;\r
35 using System.Collections;\r
36 using System.Xml;\r
37 \r
38 namespace Commons.Xml.Relaxng\r
39 {\r
40         public class RelaxngReader : XmlDefaultReader\r
41         {\r
42                 // static members.\r
43                 static RelaxngPattern relaxngGrammar;\r
44                 static XmlReader relaxngXmlReader;\r
45                 static RelaxngReader ()\r
46                 {\r
47 //                      relaxngXmlReader = new XmlTextReader ("relaxng.rng");\r
48 //                      relaxngGrammar = RelaxngPattern.Read (relaxngXmlReader);\r
49                 }\r
50 \r
51                 public static string RelaxngNS = "http://relaxng.org/ns/structure/1.0";\r
52 //              public static RelaxngPattern RelaxngGrammar {\r
53 //                      get { return relaxngGrammar; }\r
54 //              }\r
55 \r
56 \r
57                 // fields\r
58                 Stack nsStack = new Stack ();\r
59                 Stack datatypeLibraryStack = new Stack ();\r
60                 XmlResolver resolver = new XmlUrlResolver ();\r
61 \r
62                 // ctor\r
63                 public RelaxngReader (XmlReader reader)\r
64                         : this (reader, null)\r
65                 {\r
66                 }\r
67 \r
68                 public RelaxngReader (XmlReader reader, string ns)\r
69 //                      : base (reader == relaxngXmlReader ? reader : new RelaxngValidatingReader (reader, relaxngGrammar))\r
70                         : base (reader)\r
71                 {\r
72                         nsStack.Push (ns == null ? "" : ns);\r
73                         datatypeLibraryStack.Push ("");\r
74 \r
75                         if (Reader.ReadState == ReadState.Initial)\r
76                                 Read ();\r
77                         MoveToContent ();\r
78                 }\r
79 \r
80                 public XmlResolver XmlResolver {\r
81                         set { resolver = value; }\r
82                 }\r
83 \r
84                 internal XmlResolver Resolver {\r
85                         get { return resolver; }\r
86                 }\r
87 \r
88                 private void FillLocation (RelaxngElementBase el)\r
89                 {\r
90                         el.BaseUri = BaseURI;\r
91                         IXmlLineInfo li = this as IXmlLineInfo;\r
92                         el.LineNumber = li != null ? li.LineNumber : 0;\r
93                         el.LinePosition = li != null ? li.LinePosition : 0;\r
94                 }\r
95 \r
96                 // public\r
97                 public override bool Read ()\r
98                 {\r
99                         bool skipRead = false;\r
100                         bool b = false;\r
101                         bool loop = true;\r
102                         if (IsEmptyElement) { // this should be done here\r
103                                 nsStack.Pop ();\r
104                                 datatypeLibraryStack.Pop ();\r
105                         }\r
106                         do {\r
107                                 if (!skipRead)\r
108                                         b = Reader.Read ();\r
109                                 else\r
110                                         skipRead = false;\r
111                                 switch (NodeType) {\r
112                                 case XmlNodeType.ProcessingInstruction:\r
113                                 case XmlNodeType.Comment:\r
114                                 case XmlNodeType.EntityReference:\r
115                                         continue;\r
116                                 case XmlNodeType.Whitespace:\r
117                                 // Skip whitespaces except for data and param.\r
118                                 case XmlNodeType.SignificantWhitespace:\r
119                                         if (LocalName != "value" && LocalName != "param") {\r
120                                                 continue;\r
121                                         }\r
122                                         else\r
123                                                 loop = false;\r
124                                         break;\r
125                                 default:\r
126                                         if (NamespaceURI != RelaxngNS) {\r
127                                                 Reader.Skip ();\r
128                                                 skipRead = true;\r
129                                         }\r
130                                         else\r
131                                                 loop = false;\r
132                                         break;\r
133                                 }\r
134                         } while (b && loop);\r
135 \r
136                         switch (NodeType) {\r
137                         case XmlNodeType.Element:\r
138                                 if (MoveToAttribute ("ns"))\r
139                                         nsStack.Push (Value.Trim ());\r
140                                 else\r
141                                         nsStack.Push (nsStack.Peek ());\r
142 \r
143                                 if (MoveToAttribute ("datatypeLibrary")) {\r
144                                         string uriString = Value.Trim ();\r
145                                         if (uriString.Length == 0)\r
146                                                 datatypeLibraryStack.Push (String.Empty);\r
147                                         else {\r
148                                                 try {\r
149                                                         Uri uri = new Uri (uriString);\r
150                                                         // MS.NET Uri is too lamespec\r
151                                                         datatypeLibraryStack.Push (uri.ToString ());\r
152                                                 } catch (UriFormatException ex) {\r
153                                                         throw new RelaxngException (ex.Message, ex);\r
154                                                 }\r
155                                         }\r
156                                 }\r
157                                 else\r
158                                         datatypeLibraryStack.Push (datatypeLibraryStack.Peek ());\r
159                                 MoveToElement ();\r
160                                 break;\r
161 \r
162                         case XmlNodeType.EndElement:\r
163                                 nsStack.Pop ();\r
164                                 datatypeLibraryStack.Pop ();\r
165                                 break;\r
166                         }\r
167 \r
168                         return b;\r
169                 }\r
170 \r
171                 // Properties\r
172 \r
173                 public string ContextNamespace {\r
174                         get { return nsStack.Peek () as string; }\r
175                 }\r
176 \r
177                 public string DatatypeLibrary {\r
178                         get { return datatypeLibraryStack.Peek () as string; }\r
179                 }\r
180 \r
181                 // Utility methods.\r
182                 private void expect (string name)\r
183                 {\r
184                         if (NamespaceURI != RelaxngGrammar.NamespaceURI)\r
185                                 throw new RelaxngException (String.Format ("Invalid document: expected namespace {0} but found {1}", RelaxngGrammar.NamespaceURI, NamespaceURI));\r
186                         else if (LocalName != name)\r
187                                 throw new RelaxngException (String.Format ("Invalid document: expected local name {0} but found {1}", name, LocalName));\r
188                 }\r
189 \r
190                 private void expectEnd (string name)\r
191                 {\r
192                         if (NodeType != XmlNodeType.EndElement)\r
193                                 throw new RelaxngException (String.Format ("Expected EndElement but found {0}.", NodeType));\r
194                         expect (name);\r
195 \r
196                         Read ();\r
197                 }\r
198 \r
199                 // Other than name class and pattern.\r
200                 private RelaxngStart ReadStart ()\r
201                 {\r
202                         RelaxngStart s = new RelaxngStart ();\r
203                         FillLocation (s);\r
204                         expect ("start");\r
205 \r
206                         if (MoveToFirstAttribute ()) {\r
207                                 do {\r
208                                         if (NamespaceURI != String.Empty)\r
209                                                 continue;\r
210                                         switch (LocalName) {\r
211                                         case "datatypeLibrary":\r
212                                         case  "combine":\r
213                                                 break;\r
214                                         default:\r
215                                                 throw new RelaxngException ("Invalid attribute.");\r
216                                         }\r
217                                 } while (MoveToNextAttribute ());\r
218                                 MoveToElement ();\r
219                         }\r
220 \r
221                         if (MoveToAttribute ("combine")) {\r
222                                 s.Combine = Value.Trim ();\r
223                                 if (s.Combine != "choice" && s.Combine != "interleave")\r
224                                         throw new RelaxngException ("Invalid combine attribute: " + s.Combine);\r
225                         }\r
226 \r
227                         MoveToElement ();\r
228                         Read ();\r
229                         s.Pattern = ReadPattern ();\r
230                         expectEnd ("start");\r
231                         return s;\r
232                 }\r
233 \r
234                 private string GetNameAttribute ()\r
235                 {\r
236                         string name = GetSpaceStrippedAttribute ("name");\r
237                         if (name == null)\r
238                                 throw new RelaxngException ("Required attribute name is not found.");\r
239                         return XmlConvert.VerifyNCName (name);\r
240                 }\r
241 \r
242                 private string GetSpaceStrippedAttribute (string name)\r
243                 {\r
244                         string v = GetAttribute (name);\r
245                         return v != null ? v.Trim () : null;\r
246                 }\r
247 \r
248                 private RelaxngDefine ReadDefine ()\r
249                 {\r
250                         RelaxngDefine def = new RelaxngDefine ();\r
251                         FillLocation (def);\r
252                         expect ("define");\r
253                         def.Name = GetNameAttribute ();\r
254                         def.Combine = GetSpaceStrippedAttribute ("combine");\r
255 \r
256                         Read ();\r
257                         while (NodeType == XmlNodeType.Element)\r
258                                 def.Patterns.Add (ReadPattern ());\r
259                         expectEnd ("define");\r
260                         return def;\r
261                 }\r
262 \r
263                 private RelaxngParam ReadParam ()\r
264                 {\r
265                         RelaxngParam p = new RelaxngParam ();\r
266                         FillLocation (p);\r
267                         expect ("param");\r
268                         p.Name = GetNameAttribute ();\r
269                         p.Value = ReadString ().Trim ();\r
270                         expectEnd ("param");\r
271                         return p;\r
272                 }\r
273 \r
274                 // NameClass reader (only if it is element-style.)\r
275                 private RelaxngNameClass ReadNameClass ()\r
276                 {\r
277                         switch (LocalName) {\r
278                         case "name":\r
279                                 return ReadNameClassName ();\r
280                         case "anyName":\r
281                                 return ReadNameClassAnyName ();\r
282                         case "nsName":\r
283                                 return ReadNameClassNsName ();\r
284                         case "choice":\r
285                                 return ReadNameClassChoice ();\r
286                         }\r
287                         throw new RelaxngException ("Invalid name class: " + LocalName);\r
288                 }\r
289 \r
290                 private RelaxngName ReadNameClassName ()\r
291                 {\r
292                         string name = ReadString ().Trim ();\r
293                         RelaxngName rName = resolvedName (name);\r
294                         expectEnd ("name");\r
295                         return rName;\r
296                 }\r
297 \r
298                 private RelaxngAnyName ReadNameClassAnyName ()\r
299                 {\r
300                         RelaxngAnyName an = new RelaxngAnyName ();\r
301                         FillLocation (an);\r
302                         if (!IsEmptyElement) {\r
303                                 Read ();\r
304                                 if (NodeType == XmlNodeType.EndElement) {\r
305                                 } else {\r
306                                         // expect except\r
307                                         expect ("except");\r
308                                         Read ();\r
309                                         an.Except = new RelaxngExceptNameClass ();\r
310                                         FillLocation (an.Except);\r
311                                         while (NodeType == XmlNodeType.Element)\r
312                                                 an.Except.Names.Add (\r
313                                                         ReadNameClass ());\r
314                                         expectEnd ("except");\r
315                                 }\r
316                                 expectEnd ("anyName");\r
317                         } else\r
318                                 Read ();\r
319                         return an;\r
320                 }\r
321 \r
322                 private RelaxngNsName ReadNameClassNsName ()\r
323                 {\r
324                         RelaxngNsName nn = new RelaxngNsName ();\r
325                         FillLocation (nn);\r
326                         nn.Namespace = this.ContextNamespace;\r
327                         if (!IsEmptyElement) {\r
328                                 Read ();\r
329                                 if (NodeType == XmlNodeType.EndElement) {\r
330                                 } else {\r
331                                         // expect except\r
332                                         expect ("except");\r
333 //                                      Read ();\r
334                                         nn.Except = ReadNameClassExcept ();//new RelaxngExceptNameClass ();\r
335                                         FillLocation (nn.Except);\r
336                                 }\r
337                                 expectEnd ("nsName");\r
338                         } else\r
339                                 Read ();\r
340                         return nn;\r
341                 }\r
342 \r
343                 private RelaxngNameChoice ReadNameClassChoice ()\r
344                 {\r
345                         RelaxngNameChoice nc = new RelaxngNameChoice ();\r
346                         FillLocation (nc);\r
347                         if (IsEmptyElement)\r
348                                 throw new RelaxngException ("Name choice must have at least one name class.");\r
349 \r
350                         Read ();\r
351                         while (NodeType != XmlNodeType.EndElement) {\r
352                                 nc.Children.Add (ReadNameClass ());\r
353                         }\r
354                         if (nc.Children.Count == 0)\r
355                                 throw new RelaxngException ("Name choice must have at least one name class.");\r
356 \r
357                         expectEnd ("choice");\r
358                         return nc;\r
359                 }\r
360 \r
361                 private RelaxngExceptNameClass ReadNameClassExcept ()\r
362                 {\r
363                         RelaxngExceptNameClass x = new RelaxngExceptNameClass ();\r
364                         FillLocation (x);\r
365                         if (IsEmptyElement)\r
366                                 throw new RelaxngException ("Name choice must have at least one name class.");\r
367 \r
368                         Read ();\r
369                         while (NodeType != XmlNodeType.EndElement)\r
370                                 x.Names.Add (ReadNameClass ());\r
371                         if (x.Names.Count == 0)\r
372                                 throw new RelaxngException ("Name choice must have at least one name class.");\r
373 \r
374                         expectEnd ("except");\r
375                         return x;\r
376                 }\r
377 \r
378                 // Pattern reader\r
379 \r
380                 public RelaxngPattern ReadPattern ()\r
381                 {\r
382                         while (NodeType != XmlNodeType.Element)\r
383                                 if (!Read ())\r
384                                         break;\r
385 \r
386                         switch (LocalName) {\r
387                         case "element":\r
388                                 return ReadElementPattern ();\r
389                         case "attribute":\r
390                                 return ReadAttributePattern ();\r
391                         case "group":\r
392                                 return ReadGroupPattern ();\r
393                         case "interleave":\r
394                                 return ReadInterleavePattern ();\r
395                         case "choice":\r
396                                 return ReadChoicePattern ();\r
397                         case "optional":\r
398                                 return ReadOptionalPattern ();\r
399                         case "zeroOrMore":\r
400                                 return ReadZeroOrMorePattern ();\r
401                         case "oneOrMore":\r
402                                 return ReadOneOrMorePattern ();\r
403                         case "list":\r
404                                 return ReadListPattern ();\r
405                         case "mixed":\r
406                                 return ReadMixedPattern ();\r
407                         case "ref":\r
408                                 return ReadRefPattern ();\r
409                         case "parentRef":\r
410                                 return ReadParentRefPattern ();\r
411                         case "empty":\r
412                                 return ReadEmptyPattern ();\r
413                         case "text":\r
414                                 return ReadTextPattern ();\r
415                         case "data":\r
416                                 return ReadDataPattern ();\r
417                         case "value":\r
418                                 return ReadValuePattern ();\r
419                         case "notAllowed":\r
420                                 return ReadNotAllowedPattern ();\r
421                         case "externalRef":\r
422                                 return ReadExternalRefPattern ();\r
423                         case "grammar":\r
424                                 return ReadGrammarPattern ();\r
425                         }\r
426                         throw new RelaxngException ("Non-supported pattern specification: " + LocalName);\r
427                 }\r
428 \r
429                 private void ReadPatterns (RelaxngSingleContentPattern el)\r
430                 {\r
431                         do {\r
432                                 el.Patterns.Add (ReadPattern ());\r
433                         } while (NodeType == XmlNodeType.Element);\r
434                 }\r
435 \r
436                 private void ReadPatterns (RelaxngBinaryContentPattern el)\r
437                 {\r
438                         do {\r
439                                 el.Patterns.Add (ReadPattern ());\r
440                         } while (NodeType == XmlNodeType.Element);\r
441                 }\r
442 \r
443                 private RelaxngExcept ReadPatternExcept ()\r
444                 {\r
445                         RelaxngExcept x = new RelaxngExcept ();\r
446                         FillLocation (x);\r
447                         if (IsEmptyElement)\r
448                                 throw new RelaxngException ("'except' must have at least one pattern.");\r
449                         Read ();\r
450                         while (NodeType != XmlNodeType.EndElement)\r
451                                 x.Patterns.Add (ReadPattern ());\r
452                         if (x.Patterns.Count == 0)\r
453                                 throw new RelaxngException ("'except' must have at least one pattern.");\r
454 \r
455                         expectEnd ("except");\r
456                         return x;\r
457                 }\r
458 \r
459                 private RelaxngInclude ReadInclude ()\r
460                 {\r
461                         RelaxngInclude i = new RelaxngInclude ();\r
462                         FillLocation (i);\r
463                         expect ("include");\r
464                         i.NSContext = ContextNamespace;\r
465                         string href = GetSpaceStrippedAttribute ("href");\r
466                         if (href == null)\r
467                                 throw new RelaxngException ("Required attribute href was not found.");\r
468                         XmlResolver res = resolver != null ? resolver : new XmlUrlResolver ();\r
469                         i.Href = res.ResolveUri (BaseURI != null ? new Uri (BaseURI) : null, href).AbsoluteUri;\r
470                         if (!IsEmptyElement) {\r
471                                 Read ();\r
472                                 this.readGrammarIncludeContent (i.Starts, i.Defines, i.Divs, null);\r
473                                 expectEnd ("include");\r
474                         }\r
475                         else\r
476                                 Read ();\r
477                         return i;\r
478                 }\r
479 \r
480                 private void readGrammarIncludeContent (IList starts, IList defines, IList divs, IList includes)\r
481                 {\r
482                         while (NodeType == XmlNodeType.Element) {\r
483                                 switch (LocalName) {\r
484                                 case "start":\r
485                                         starts.Add (ReadStart ());\r
486                                         break;\r
487                                 case "define":\r
488                                         defines.Add (ReadDefine ());\r
489                                         break;\r
490                                 case "div":\r
491                                         divs.Add (ReadDiv (includes != null));\r
492                                         break;\r
493                                 case "include":\r
494                                         if (includes != null)\r
495                                                 includes.Add (ReadInclude ());\r
496                                         else\r
497                                                 throw new RelaxngException ("Unexpected content: " + Name);\r
498                                         break;\r
499                                 default:\r
500                                         throw new RelaxngException ("Unexpected content: " + Name);\r
501                                 }\r
502                         }\r
503                 }\r
504 \r
505                 private RelaxngDiv ReadDiv (bool allowIncludes)\r
506                 {\r
507                         expect ("div");\r
508                         RelaxngDiv div = new RelaxngDiv ();\r
509                         FillLocation (div);\r
510                         if (!IsEmptyElement) {\r
511                                 Read ();\r
512                                 readGrammarIncludeContent (div.Starts, div.Defines, div.Divs, div.Includes);\r
513                                 expectEnd ("div");\r
514                         }\r
515                         else\r
516                                 Read ();\r
517                         return div;\r
518                 }\r
519 \r
520                 private RelaxngName resolvedName (string nameSpec)\r
521                 {\r
522                         int colonAt = nameSpec.IndexOf (':');\r
523                         string prefix = (colonAt < 0) ? "" : nameSpec.Substring (0, colonAt);\r
524                         string local = (colonAt < 0) ? nameSpec : nameSpec.Substring (colonAt + 1, nameSpec.Length - colonAt - 1);\r
525                         string uri = ContextNamespace;\r
526 \r
527                         if (prefix != "") {\r
528                                 uri = LookupNamespace (prefix);\r
529                                 if (uri == null)\r
530                                         throw new RelaxngException ("Undeclared prefix in name component: " + nameSpec);\r
531                         }\r
532                         RelaxngName n = new RelaxngName (local, uri);\r
533                         FillLocation (n);\r
534                         return n;\r
535                 }\r
536 \r
537                 private RelaxngElement ReadElementPattern ()\r
538                 {\r
539                         RelaxngElement el = new RelaxngElement ();\r
540                         FillLocation (el);\r
541 \r
542                         if (MoveToFirstAttribute ()) {\r
543                                 do {\r
544                                         if (NamespaceURI != String.Empty)\r
545                                                 continue;\r
546                                         switch (LocalName) {\r
547                                         case "datatypeLibrary":\r
548                                         case  "name":\r
549                                         case "ns":\r
550                                                 break;\r
551                                         default:\r
552                                                 throw new RelaxngException ("Invalid attribute.");\r
553                                         }\r
554                                 } while (MoveToNextAttribute ());\r
555                                 MoveToElement ();\r
556                         }\r
557 \r
558                         // try to get name from attribute.\r
559                         if (MoveToAttribute ("name"))\r
560                                 el.NameClass = resolvedName (XmlConvert.VerifyName (Value.Trim ()));\r
561                         MoveToElement ();\r
562                         Read ();\r
563 \r
564                         // read nameClass from content.\r
565                         if (el.NameClass == null)\r
566                                 el.NameClass = ReadNameClass ();\r
567 \r
568                         // read patterns.\r
569                         this.ReadPatterns (el);\r
570 \r
571                         expectEnd ("element");\r
572 \r
573                         if (el.NameClass == null)\r
574                                 throw new RelaxngException ("Name class was not specified.");\r
575                         return el;\r
576                 }\r
577 \r
578                 private RelaxngAttribute ReadAttributePattern ()\r
579                 {\r
580                         RelaxngAttribute attr = new RelaxngAttribute ();\r
581                         FillLocation (attr);\r
582 \r
583                         if (MoveToFirstAttribute ()) {\r
584                                 do {\r
585                                         if (NamespaceURI != String.Empty)\r
586                                                 continue;\r
587                                         switch (LocalName) {\r
588                                         case "datatypeLibrary":\r
589                                         case  "name":\r
590                                         case "ns":\r
591                                                 break;\r
592                                         default:\r
593                                                 throw new RelaxngException ("Invalid attribute.");\r
594                                         }\r
595                                 } while (MoveToNextAttribute ());\r
596                                 MoveToElement ();\r
597                         }\r
598 \r
599                         string ns = GetSpaceStrippedAttribute ("ns");\r
600 \r
601                         // try to get name from attribute.\r
602                         if (MoveToAttribute ("name")) {\r
603 //                              attr.NameClass = resolvedName (XmlConvert.VerifyName (Value.Trim ()), false);\r
604                                 RelaxngName nc = new RelaxngName ();\r
605                                 string name = XmlConvert.VerifyName (Value.Trim ());\r
606                                 if (name.IndexOf (':') > 0)\r
607                                         nc = resolvedName (name);\r
608                                 else {\r
609                                         nc.LocalName = name;\r
610                                         nc.Namespace = ns == null ? String.Empty : ns;\r
611                                 }\r
612                                 attr.NameClass = nc;\r
613                         }\r
614 \r
615                         MoveToElement ();\r
616                         if (!IsEmptyElement) {\r
617                                 Read ();\r
618                                 // read nameClass from content.\r
619                                 if (attr.NameClass == null)\r
620                                         attr.NameClass = ReadNameClass ();\r
621 \r
622                                 if (NodeType == XmlNodeType.Element)\r
623                                         attr.Pattern = ReadPattern ();\r
624 \r
625                                 expectEnd ("attribute");\r
626                         } else\r
627                                 Read ();\r
628 \r
629                         if (attr.NameClass == null)\r
630                                 throw new RelaxngException ("Name class was not specified.");\r
631                         return attr;\r
632                 }\r
633 \r
634                 private RelaxngGrammar ReadGrammarPattern ()\r
635                 {\r
636                         RelaxngGrammar grammar = new RelaxngGrammar ();\r
637                         FillLocation (grammar);\r
638                         Read ();\r
639                         this.readGrammarIncludeContent (grammar.Starts, grammar.Defines, grammar.Divs, grammar.Includes);\r
640                         expectEnd ("grammar");\r
641 \r
642                         return grammar;\r
643                 }\r
644 \r
645                 private RelaxngRef ReadRefPattern ()\r
646                 {\r
647                         RelaxngRef r = new RelaxngRef ();\r
648                         FillLocation (r);\r
649                         expect ("ref");\r
650                         r.Name = GetNameAttribute ();\r
651                         if (!IsEmptyElement) {\r
652                                 Read ();\r
653                                 expectEnd ("ref");\r
654                         }\r
655                         else\r
656                                 Read ();\r
657                         return r;\r
658                 }\r
659 \r
660                 private RelaxngExternalRef ReadExternalRefPattern ()\r
661                 {\r
662                         RelaxngExternalRef r = new RelaxngExternalRef ();\r
663                         FillLocation (r);\r
664                         expect ("externalRef");\r
665                         string href = GetSpaceStrippedAttribute ("href");\r
666                         if (href == null)\r
667                                 throw new RelaxngException ("Required attribute href was not found.");\r
668                         XmlResolver res = resolver != null ? resolver : new XmlUrlResolver ();\r
669                         r.Href = res.ResolveUri (BaseURI != null ? new Uri (BaseURI) : null, href).AbsoluteUri;\r
670                         r.NSContext = ContextNamespace;\r
671                         if (!IsEmptyElement) {\r
672                                 Read ();\r
673                                 expectEnd ("externalRef");\r
674                         }\r
675                         else\r
676                                 Read ();\r
677                         return r;\r
678                 }\r
679 \r
680                 private RelaxngParentRef ReadParentRefPattern ()\r
681                 {\r
682                         RelaxngParentRef r = new RelaxngParentRef ();\r
683                         FillLocation (r);\r
684                         expect ("parentRef");\r
685                         r.Name = GetNameAttribute ();\r
686                         if (!IsEmptyElement) {\r
687                                 Read ();\r
688                                 expectEnd ("parentRef");\r
689                         }\r
690                         else\r
691                                 Read ();\r
692                         return r;\r
693                 }\r
694 \r
695                 private RelaxngEmpty ReadEmptyPattern ()\r
696                 {\r
697                         expect ("empty");\r
698 \r
699                         if (MoveToFirstAttribute ()) {\r
700                                 do {\r
701                                         if (NamespaceURI == String.Empty && LocalName != "datatypeLibrary")\r
702                                                 throw new RelaxngException ("Invalid attribute.");\r
703                                 } while (MoveToNextAttribute ());\r
704                                 MoveToElement ();\r
705                         }\r
706 \r
707                         if (!IsEmptyElement) {\r
708                                 Read ();\r
709                                 expectEnd ("empty");\r
710                         }\r
711                         else\r
712                                 Read ();\r
713 \r
714                         RelaxngEmpty empty = new RelaxngEmpty ();\r
715                         FillLocation (empty);\r
716                         return empty;\r
717                 }\r
718 \r
719                 private RelaxngText ReadTextPattern ()\r
720                 {\r
721                         expect ("text");\r
722 \r
723                         if (MoveToFirstAttribute ()) {\r
724                                 do {\r
725                                         if (NamespaceURI == String.Empty && LocalName != "datatypeLibrary")\r
726                                                 throw new RelaxngException ("Invalid attribute.");\r
727                                 } while (MoveToNextAttribute ());\r
728                                 MoveToElement ();\r
729                         }\r
730 \r
731                         if (!IsEmptyElement) {\r
732                                 Read ();\r
733                                 expectEnd ("text");\r
734                         }\r
735                         else\r
736                                 Read ();\r
737 \r
738                         RelaxngText t = new RelaxngText ();\r
739                         FillLocation (t);\r
740                         return t;\r
741                 }\r
742 \r
743                 private RelaxngData ReadDataPattern ()\r
744                 {\r
745                         RelaxngData data = new RelaxngData ();\r
746                         FillLocation (data);\r
747 \r
748                         expect ("data");\r
749                         data.Type = GetSpaceStrippedAttribute ("type");\r
750                         if (data.Type == null)\r
751                                 throw new RelaxngException ("Attribute type is required.");\r
752                         data.DatatypeLibrary = DatatypeLibrary;\r
753 \r
754                         if (MoveToFirstAttribute ()) {\r
755                                 do {\r
756                                         if (NamespaceURI != String.Empty)\r
757                                                 continue;\r
758                                         switch (LocalName) {\r
759                                         case "datatypeLibrary":\r
760                                         case "type":\r
761                                                 break;\r
762                                         default:\r
763                                                 throw new RelaxngException ("Invalid attribute.");\r
764                                         }\r
765                                 } while (MoveToNextAttribute ());\r
766                                 MoveToElement ();\r
767                         }\r
768 \r
769                         if (!IsEmptyElement) {\r
770                                 Read ();\r
771                                 while (Name == "param") {\r
772                                         data.ParamList.Add (ReadParam ());\r
773                                 }\r
774                                 if (LocalName == "except")\r
775                                         data.Except = ReadPatternExcept ();\r
776                                 expectEnd ("data");\r
777                         } else\r
778                                 Read ();\r
779 \r
780                         return data;\r
781                 }\r
782 \r
783                 private RelaxngValue ReadValuePattern ()\r
784                 {\r
785                         RelaxngValue v = new RelaxngValue ();\r
786                         FillLocation (v);\r
787                         expect ("value");\r
788 \r
789                         if (MoveToFirstAttribute ()) {\r
790                                 do {\r
791                                         if (NamespaceURI != String.Empty)\r
792                                                 continue;\r
793                                         switch (LocalName) {\r
794                                         case "datatypeLibrary":\r
795                                         case "type":\r
796                                         case "ns":\r
797                                                 break;\r
798                                         default:\r
799                                                 throw new RelaxngException ("Invalid attribute.");\r
800                                         }\r
801                                 } while (MoveToNextAttribute ());\r
802                                 MoveToElement ();\r
803                         }\r
804 \r
805                         if (MoveToAttribute ("type")) {\r
806                                 v.Type = Value.Trim ();\r
807                                 v.DatatypeLibrary = DatatypeLibrary;\r
808                         } else {\r
809                                 v.Type = "token";\r
810                                 v.DatatypeLibrary = "";\r
811                         }\r
812 //                      v.Namespace = GetSpaceStrippedAttribute ("ns");\r
813                         MoveToElement ();\r
814                         if (IsEmptyElement) {\r
815                                 v.Value = String.Empty;\r
816                                 Read ();\r
817                         } else {\r
818                                 v.Value = ReadString ();\r
819                                 expectEnd ("value");\r
820                         }\r
821 \r
822                         return v;\r
823                 }\r
824 \r
825                 private RelaxngList ReadListPattern ()\r
826                 {\r
827                         RelaxngList list = new RelaxngList ();\r
828                         FillLocation (list);\r
829                         expect ("list");\r
830                         Read ();\r
831                         ReadPatterns (list);\r
832                         expectEnd ("list");\r
833                         return list;\r
834                 }\r
835 \r
836                 private RelaxngOneOrMore ReadOneOrMorePattern ()\r
837                 {\r
838                         RelaxngOneOrMore o = new RelaxngOneOrMore ();\r
839                         FillLocation (o);\r
840                         expect ("oneOrMore");\r
841                         Read ();\r
842                         ReadPatterns (o);\r
843                         expectEnd ("oneOrMore");\r
844                         return o;\r
845                 }\r
846 \r
847                 private RelaxngZeroOrMore ReadZeroOrMorePattern ()\r
848                 {\r
849                         RelaxngZeroOrMore o = new RelaxngZeroOrMore ();\r
850                         FillLocation (o);\r
851                         expect ("zeroOrMore");\r
852                         Read ();\r
853                         ReadPatterns (o);\r
854                         expectEnd ("zeroOrMore");\r
855                         return o;\r
856                 }\r
857 \r
858                 private RelaxngOptional ReadOptionalPattern ()\r
859                 {\r
860                         RelaxngOptional o = new RelaxngOptional ();\r
861                         FillLocation (o);\r
862                         expect ("optional");\r
863                         Read ();\r
864                         ReadPatterns (o);\r
865                         expectEnd ("optional");\r
866                         return o;\r
867                 }\r
868 \r
869                 private RelaxngMixed ReadMixedPattern ()\r
870                 {\r
871                         RelaxngMixed o = new RelaxngMixed ();\r
872                         FillLocation (o);\r
873                         expect ("mixed");\r
874                         Read ();\r
875                         ReadPatterns (o);\r
876                         expectEnd ("mixed");\r
877                         return o;\r
878                 }\r
879 \r
880                 private RelaxngGroup ReadGroupPattern ()\r
881                 {\r
882                         RelaxngGroup g = new RelaxngGroup ();\r
883                         FillLocation (g);\r
884                         expect ("group");\r
885                         Read ();\r
886                         ReadPatterns (g);\r
887                         expectEnd ("group");\r
888                         return g;\r
889                 }\r
890 \r
891                 private RelaxngInterleave ReadInterleavePattern ()\r
892                 {\r
893                         RelaxngInterleave i = new RelaxngInterleave ();\r
894                         FillLocation (i);\r
895                         expect ("interleave");\r
896                         Read ();\r
897                         ReadPatterns (i);\r
898                         expectEnd ("interleave");\r
899                         return i;\r
900                 }\r
901 \r
902                 private RelaxngChoice ReadChoicePattern ()\r
903                 {\r
904                         RelaxngChoice c = new RelaxngChoice ();\r
905                         FillLocation (c);\r
906                         expect ("choice");\r
907                         Read ();\r
908                         ReadPatterns (c);\r
909                         expectEnd ("choice");\r
910                         return c;\r
911                 }\r
912 \r
913                 private RelaxngNotAllowed ReadNotAllowedPattern ()\r
914                 {\r
915                         expect ("notAllowed");\r
916                         if (!IsEmptyElement) {\r
917                                 Read ();\r
918                                 expectEnd ("notAllowed");\r
919                         }\r
920                         else\r
921                                 Read ();\r
922                         RelaxngNotAllowed na = new RelaxngNotAllowed ();\r
923                         FillLocation (na);\r
924                         return na;\r
925                 }\r
926         }\r
927 }