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