2 // Commons.Xml.Relaxng.RelaxngValidatingReader
5 // Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
7 // 2003 Atsushi Enomoto. "No rights reserved."
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:
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
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.
34 using System
.Collections
;
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
)
61 this.pattern
= pattern
;
65 RelaxngPattern pattern
;
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
;
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
) {
94 vState
= pattern
.StartPattern
;
96 bool ret
= reader
.Read ();
98 switch (reader
.NodeType
) {
99 case XmlNodeType
.Element
:
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 ()) {
112 if (reader
.Name
.IndexOf ("xmlns:") == 0 || reader
.Name
== "xmlns")
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 ());
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
;
134 case XmlNodeType
.EndElement
:
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
));
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))
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
));