**** Merged from MCS ****
[mono-project.git] / mcs / class / Commons.Xml.Relaxng / Commons.Xml.Relaxng / RelaxngValidatingReader.cs
blob9e458a5c3255b85e6969ccedb9fa30389eb2756b
1 //
2 // Commons.Xml.Relaxng.RelaxngValidatingReader
3 //
4 // Author:
5 // Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
6 //
7 // 2003 Atsushi Enomoto. "No rights reserved."
8 //
9 // Copyright (c) 2004 Novell Inc.
10 // All rights reserved
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.
33 using System;
34 using System.Collections;
35 using System.Xml;
36 using Commons.Xml.Relaxng.Derivative;
38 namespace Commons.Xml.Relaxng
40 public class RelaxngValidatingReader : XmlDefaultReader
42 public RelaxngValidatingReader (XmlReader reader)
43 : this (reader, (RelaxngPattern) null)
47 public RelaxngValidatingReader (XmlReader reader, XmlReader grammarXml)
48 : this (reader, grammarXml, null)
52 public RelaxngValidatingReader (XmlReader reader, XmlReader grammarXml, RelaxngDatatypeProvider provider)
53 : this (reader, RelaxngGrammar.Read (grammarXml, provider))
57 public RelaxngValidatingReader (XmlReader reader, RelaxngPattern pattern)
58 : base (reader)
60 this.reader = reader;
61 this.pattern = pattern;
64 XmlReader reader;
65 RelaxngPattern pattern;
66 RdpPattern vState;
67 RdpPattern prevState; // Mainly for debugging.
68 ArrayList PredefinedAttributes = new ArrayList ();
70 internal string CurrentStateXml {
71 get { return RdpUtil.DebugRdpPattern (vState, new Hashtable ()); }
74 internal string PreviousStateXml {
75 get { return RdpUtil.DebugRdpPattern (prevState, new Hashtable ()); }
78 private RelaxngException createValidationError (string message)
80 IXmlLineInfo li = reader as IXmlLineInfo;
81 string lineInfo = reader.BaseURI;
82 if (li != null)
83 lineInfo += String.Format (" line {0}, column {1}",
84 li.LineNumber, li.LinePosition);
85 return new RelaxngException (message + lineInfo, prevState);
88 public override bool Read ()
90 if (!pattern.IsCompiled) {
91 pattern.Compile ();
93 if (vState == null)
94 vState = pattern.StartPattern;
96 bool ret = reader.Read ();
98 switch (reader.NodeType) {
99 case XmlNodeType.Element:
100 // StartTagOpenDeriv
101 prevState = vState;
102 vState = vState.StartTagOpenDeriv (
103 reader.LocalName, reader.NamespaceURI);
104 if (vState.PatternType == RelaxngPatternType.NotAllowed)
105 throw createValidationError (String.Format ("Invalid start tag found. LocalName = {0}, NS = {1}. ", reader.LocalName, reader.NamespaceURI));
107 // AttsDeriv equals to for each AttDeriv
108 // if (reader.AttributeCount > 0) {
109 string elementNS = reader.NamespaceURI;
110 if (reader.MoveToFirstAttribute ()) {
111 do {
112 if (reader.Name.IndexOf ("xmlns:") == 0 || reader.Name == "xmlns")
113 continue;
115 prevState = vState;
116 string attrNS = /*reader.NamespaceURI == "" ? elementNS :*/ reader.NamespaceURI;
117 vState = vState.AttDeriv (reader.LocalName, attrNS, reader.GetAttribute (reader.Name), this);
118 if (vState.PatternType == RelaxngPatternType.NotAllowed)
119 throw createValidationError (String.Format ("Invalid attribute found. LocalName = {0}, NS = {1}. ", reader.LocalName, reader.NamespaceURI));
120 } while (reader.MoveToNextAttribute ());
121 MoveToElement ();
124 // StarTagCloseDeriv
125 prevState = vState;
126 vState = vState.StartTagCloseDeriv ();
127 if (vState.PatternType == RelaxngPatternType.NotAllowed)
128 throw createValidationError (String.Format ("Invalid start tag closing found. LocalName = {0}, NS = {1}. ", reader.LocalName, reader.NamespaceURI));
130 // if it is empty, then redirect to EndElement
131 if (reader.IsEmptyElement)
132 goto case XmlNodeType.EndElement;
133 break;
134 case XmlNodeType.EndElement:
135 // EndTagDeriv
136 prevState = vState;
137 vState = vState.EndTagDeriv ();
138 if (vState.PatternType == RelaxngPatternType.NotAllowed)
139 throw createValidationError (String.Format ("Invalid end tag found. LocalName = {0}, NS = {1}. ", reader.LocalName, reader.NamespaceURI));
140 break;
141 case XmlNodeType.CDATA:
142 case XmlNodeType.Text:
143 case XmlNodeType.SignificantWhitespace:
144 // Whitespace cannot be skipped because data and
145 // value types are required to validate whitespaces.
146 // if (Util.IsWhitespace (Value))
147 // break;
148 prevState = vState;
149 vState = vState.TextDeriv (this.Value, reader);
150 if (vState.PatternType == RelaxngPatternType.NotAllowed)
151 throw createValidationError (String.Format ("Invalid text found. Text value = {0} ", reader.Value));
152 break;
155 return ret;