1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 
5 using Xunit.Abstractions;
6 using System;
7 using System.IO;
8 using System.Text;
9 using System.Xml;
10 using System.Xml.Schema;
11 
12 public enum NodeFlags
13 {
14     None = 0,
15     EmptyElement = 1,
16     HasValue = 2,
17     SingleQuote = 4,
18     DefaultAttribute = 8,
19     UnparsedEntities = 16,
20     IsWhitespace = 32,
21     DocumentRoot = 64,
22     AttributeTextNode = 128,
23     MixedContent = 256,
24     Indent = 512
25 }
26 
27 abstract public class CXmlBase
28 {
29     protected XmlNodeType _nType;
30     protected string _strName;
31     protected string _strLocalName;
32     protected string _strPrefix;
33     protected string _strNamespace;
34     internal int _nDepth;
35     internal NodeFlags _eFlags = NodeFlags.None;
36     internal CXmlBase _rNextNode = null;
37     internal CXmlBase _rParentNode = null;
38     internal CXmlBase _rFirstChildNode = null;
39     internal CXmlBase _rLastChildNode = null;
40     internal int _nChildNodes = 0;
41 
42     //
43     // Constructors
44     //
CXmlBase(string strPrefix, string strName, string strLocalName, XmlNodeType NodeType, string strNamespace)45     public CXmlBase(string strPrefix, string strName, string strLocalName, XmlNodeType NodeType, string strNamespace)
46     {
47         _strPrefix = strPrefix;
48         _strName = strName;
49         _strLocalName = strLocalName;
50         _nType = NodeType;
51         _strNamespace = strNamespace;
52     }
53 
CXmlBase(string strPrefix, string strName, XmlNodeType NodeType, string strNamespace)54     public CXmlBase(string strPrefix, string strName, XmlNodeType NodeType, string strNamespace)
55         : this(strPrefix, strName, strName, NodeType, strNamespace)
56     { }
57 
CXmlBase(string strPrefix, string strName, XmlNodeType NodeType)58     public CXmlBase(string strPrefix, string strName, XmlNodeType NodeType)
59         : this(strPrefix, strName, strName, NodeType, "")
60     { }
61 
CXmlBase(string strName, XmlNodeType NodeType)62     public CXmlBase(string strName, XmlNodeType NodeType)
63         : this("", strName, strName, NodeType, "")
64     { }
65 
66     //
67     // Virtual Methods and Properties
68     //
Write(XmlWriter rXmlWriter)69     abstract public void Write(XmlWriter rXmlWriter);
70 
WriteXml(TextWriter rTW)71     abstract public void WriteXml(TextWriter rTW);
72 
73     abstract public string Value
74     { get; }
75 
76     //
77     // Public Methods and Properties
78     //
79     public string Name
80     {
81         get { return _strName; }
82     }
83 
84     public string LocalName
85     {
86         get { return _strLocalName; }
87     }
88 
89     public string Prefix
90     {
91         get { return _strPrefix; }
92     }
93 
94     public string Namespace
95     {
96         get { return _strNamespace; }
97     }
98 
99     public int Depth
100     {
101         get { return _nDepth; }
102     }
103 
104     public XmlNodeType NodeType
105     {
106         get { return _nType; }
107     }
108 
109     public NodeFlags Flags
110     {
111         get { return _eFlags; }
112     }
113 
114     public int ChildNodeCount
115     {
116         get { return _nChildNodes; }
117     }
118 
InsertNode(CXmlBase rNode)119     public void InsertNode(CXmlBase rNode)
120     {
121         if (_rFirstChildNode == null)
122         {
123             _rFirstChildNode = _rLastChildNode = rNode;
124         }
125         else
126         {
127             _rLastChildNode._rNextNode = rNode;
128             _rLastChildNode = rNode;
129         }
130 
131         if ((this._eFlags & NodeFlags.IsWhitespace) == 0)
132             _nChildNodes++;
133 
134         rNode._rParentNode = this;
135     }
136 
137     //
138     // Internal Methods and Properties
139     //
_Child(int n)140     internal CXmlBase _Child(int n)
141     {
142         int i;
143         int j;
144         CXmlBase rChild = _rFirstChildNode;
145 
146         for (i = 0, j = 0; rChild != null; i++, rChild = rChild._rNextNode)
147         {
148             if ((rChild._eFlags & NodeFlags.IsWhitespace) == 0)
149             {
150                 if (j++ == n) break;
151             }
152         }
153 
154         return rChild;
155     }
156 
_Child(string str)157     internal CXmlBase _Child(string str)
158     {
159         CXmlBase rChild;
160 
161         for (rChild = _rFirstChildNode; rChild != null; rChild = rChild._rNextNode)
162             if (rChild.Name == str) break;
163 
164         return rChild;
165     }
166 }
167 
168 public class CXmlAttribute : CXmlBase
169 {
170     //
171     // Constructor
172     //
CXmlAttribute(XmlReader rXmlReader)173     public CXmlAttribute(XmlReader rXmlReader)
174         : base(rXmlReader.Prefix, rXmlReader.Name, rXmlReader.LocalName, rXmlReader.NodeType, rXmlReader.NamespaceURI)
175     {
176         if (rXmlReader.IsDefault)
177             _eFlags |= NodeFlags.DefaultAttribute;
178 
179         if (rXmlReader.QuoteChar == '\'')
180             _eFlags |= NodeFlags.SingleQuote;
181     }
182 
183     //
184     // Public Methods and Properties (Override)
185     //
Write(XmlWriter rXmlWriter)186     override public void Write(XmlWriter rXmlWriter)
187     {
188         CXmlBase rNode;
189 
190         if ((this._eFlags & NodeFlags.DefaultAttribute) == 0)
191         {
192             if (rXmlWriter is XmlTextWriter)
193                 ((XmlTextWriter)rXmlWriter).QuoteChar = this.Quote;
194 
195             rXmlWriter.WriteStartAttribute(this.Prefix, this.LocalName, this.Namespace);
196 
197             for (rNode = this._rFirstChildNode; rNode != null; rNode = rNode._rNextNode)
198             {
199                 rNode.Write(rXmlWriter);
200             }
201 
202             rXmlWriter.WriteEndAttribute();
203         }
204     }
205 
WriteXml(TextWriter rTW)206     override public void WriteXml(TextWriter rTW)
207     {
208         if ((this._eFlags & NodeFlags.DefaultAttribute) == 0)
209         {
210             CXmlBase rNode;
211 
212             rTW.Write(' ' + this.Name + '=' + this.Quote);
213             for (rNode = this._rFirstChildNode; rNode != null; rNode = rNode._rNextNode)
214             {
215                 rNode.WriteXml(rTW);
216             }
217             rTW.Write(this.Quote);
218         }
219     }
220 
221     //
222     // Public Methods and Properties
223     //
224     override public string Value
225     {
226         get
227         {
228             CXmlNode rNode;
229             string strValue = string.Empty;
230 
231             for (rNode = (CXmlNode)this._rFirstChildNode; rNode != null; rNode = rNode.NextNode)
232                 strValue += rNode.Value;
233 
234             return strValue;
235         }
236     }
237 
238     public CXmlAttribute NextAttribute
239     {
240         get { return (CXmlAttribute)this._rNextNode; }
241     }
242 
243     public char Quote
244     {
245         get { return ((base._eFlags & NodeFlags.SingleQuote) != 0 ? '\'' : '"'); }
246         set { if (value == '\'') base._eFlags |= NodeFlags.SingleQuote; else base._eFlags &= ~NodeFlags.SingleQuote; }
247     }
248 
249     public CXmlNode FirstChild
250     {
251         get { return (CXmlNode)base._rFirstChildNode; }
252     }
253 
Child(int n)254     public CXmlNode Child(int n)
255     {
256         return (CXmlNode)base._Child(n);
257     }
258 
Child(string str)259     public CXmlNode Child(string str)
260     {
261         return (CXmlNode)base._Child(str);
262     }
263 }
264 
265 public class CXmlNode : CXmlBase
266 {
267     internal string _strValue = null;
268     private CXmlAttribute _rFirstAttribute = null;
269     private CXmlAttribute _rLastAttribute = null;
270     private int _nAttributeCount = 0;
271 
272     //
273     // Constructors
274     //
CXmlNode(string strPrefix, string strName, XmlNodeType NodeType)275     public CXmlNode(string strPrefix, string strName, XmlNodeType NodeType)
276         : base(strPrefix, strName, NodeType)
277     { }
278 
CXmlNode(XmlReader rXmlReader)279     public CXmlNode(XmlReader rXmlReader)
280         : base(rXmlReader.Prefix, rXmlReader.Name, rXmlReader.LocalName, rXmlReader.NodeType, rXmlReader.NamespaceURI)
281     {
282         _eFlags |= CXmlCache._eDefaultFlags;
283 
284         if (NodeType == XmlNodeType.Whitespace ||
285             NodeType == XmlNodeType.SignificantWhitespace)
286         {
287             _eFlags |= NodeFlags.IsWhitespace;
288         }
289 
290         if (rXmlReader.IsEmptyElement)
291         {
292             _eFlags |= NodeFlags.EmptyElement;
293         }
294 
295         if (rXmlReader.HasValue)
296         {
297             _eFlags |= NodeFlags.HasValue;
298             _strValue = rXmlReader.Value;
299         }
300     }
301 
302     //
303     // Public Methods and Properties (Override)
304     //
Write(XmlWriter rXmlWriter)305     override public void Write(XmlWriter rXmlWriter)
306     {
307         CXmlBase rNode;
308         CXmlAttribute rAttribute;
309         string DocTypePublic = null;
310         string DocTypeSystem = null;
311 
312         switch (this.NodeType)
313         {
314             case XmlNodeType.CDATA:
315                 rXmlWriter.WriteCData(this._strValue);
316                 break;
317 
318             case XmlNodeType.Comment:
319                 rXmlWriter.WriteComment(this._strValue);
320                 break;
321 
322             case XmlNodeType.DocumentType:
323                 for (rAttribute = _rFirstAttribute; rAttribute != null; rAttribute = rAttribute.NextAttribute)
324                 {
325                     if (rAttribute.Name == "PUBLIC")
326                     { DocTypePublic = rAttribute.Value; }
327                     if (rAttribute.Name == "SYSTEM")
328                     { DocTypeSystem = rAttribute.Value; }
329                 }
330                 rXmlWriter.WriteDocType(this.Name, DocTypePublic, DocTypeSystem, this._strValue);
331                 break;
332 
333             case XmlNodeType.EntityReference:
334                 rXmlWriter.WriteEntityRef(this.Name);
335                 break;
336 
337             case XmlNodeType.ProcessingInstruction:
338                 rXmlWriter.WriteProcessingInstruction(this.Name, this._strValue);
339                 break;
340 
341             case XmlNodeType.Text:
342                 if (this.Name == string.Empty)
343                 {
344                     if ((this.Flags & NodeFlags.UnparsedEntities) == 0)
345                     {
346                         rXmlWriter.WriteString(this._strValue);
347                     }
348                     else
349                     {
350                         rXmlWriter.WriteRaw(this._strValue.ToCharArray(), 0, this._strValue.Length);
351                     }
352                 }
353                 else
354                 {
355                     if (this._strName[0] == '#')
356                         rXmlWriter.WriteCharEntity(this._strValue[0]);
357                     else
358                         rXmlWriter.WriteEntityRef(this.Name);
359                 }
360                 break;
361 
362             case XmlNodeType.Whitespace:
363             case XmlNodeType.SignificantWhitespace:
364                 if ((this._rParentNode._eFlags & NodeFlags.DocumentRoot) != 0)
365                     rXmlWriter.WriteRaw(this._strValue.ToCharArray(), 0, this._strValue.Length);
366                 else
367                     rXmlWriter.WriteString(this._strValue);
368                 break;
369 
370             case XmlNodeType.Element:
371                 rXmlWriter.WriteStartElement(this.Prefix, this.LocalName, null);
372 
373                 for (rAttribute = _rFirstAttribute; rAttribute != null; rAttribute = rAttribute.NextAttribute)
374                 {
375                     rAttribute.Write(rXmlWriter);
376                 }
377 
378                 if ((this.Flags & NodeFlags.EmptyElement) == 0)
379                     rXmlWriter.WriteString(string.Empty);
380 
381                 for (rNode = base._rFirstChildNode; rNode != null; rNode = rNode._rNextNode)
382                 {
383                     rNode.Write(rXmlWriter);
384                 }
385 
386                 // Should only produce empty tag if the original document used empty tag
387                 if ((this.Flags & NodeFlags.EmptyElement) == 0)
388                     rXmlWriter.WriteFullEndElement();
389                 else
390                     rXmlWriter.WriteEndElement();
391 
392                 break;
393 
394             case XmlNodeType.XmlDeclaration:
395                 rXmlWriter.WriteRaw("<?xml " + this._strValue + "?>");
396                 break;
397 
398             default:
399                 throw (new Exception("Node.Write: Unhandled node type " + this.NodeType.ToString()));
400         }
401     }
402 
WriteXml(TextWriter rTW)403     override public void WriteXml(TextWriter rTW)
404     {
405         String strXml;
406         CXmlAttribute rAttribute;
407         CXmlBase rNode;
408 
409         switch (this._nType)
410         {
411             case XmlNodeType.Text:
412                 if (this._strName == "")
413                 {
414                     rTW.Write(this._strValue);
415                 }
416                 else
417                 {
418                     if (this._strName.StartsWith("#"))
419                     {
420                         rTW.Write("&" + Convert.ToString(Convert.ToInt32(this._strValue[0])) + ";");
421                     }
422                     else
423                     {
424                         rTW.Write("&" + this.Name + ";");
425                     }
426                 }
427                 break;
428 
429             case XmlNodeType.Whitespace:
430             case XmlNodeType.SignificantWhitespace:
431             case XmlNodeType.DocumentType:
432                 rTW.Write(this._strValue);
433                 break;
434 
435             case XmlNodeType.Element:
436                 strXml = this.Name;
437                 rTW.Write('<' + strXml);
438 
439                 //Put in all the Attributes
440                 for (rAttribute = _rFirstAttribute; rAttribute != null; rAttribute = rAttribute.NextAttribute)
441                 {
442                     rAttribute.WriteXml(rTW);
443                 }
444 
445                 //If there is children, put those in, otherwise close the tag.
446                 if ((base._eFlags & NodeFlags.EmptyElement) == 0)
447                 {
448                     rTW.Write('>');
449 
450                     for (rNode = base._rFirstChildNode; rNode != null; rNode = rNode._rNextNode)
451                     {
452                         rNode.WriteXml(rTW);
453                     }
454 
455                     rTW.Write("</" + strXml + ">");
456                 }
457                 else
458                 {
459                     rTW.Write(" />");
460                 }
461 
462                 break;
463 
464             case XmlNodeType.EntityReference:
465                 rTW.Write("&" + this._strName + ";");
466                 break;
467 
468             case XmlNodeType.Notation:
469                 rTW.Write("<!NOTATION " + this._strValue + ">");
470                 break;
471 
472             case XmlNodeType.CDATA:
473                 rTW.Write("<![CDATA[" + this._strValue + "]]>");
474                 break;
475 
476             case XmlNodeType.XmlDeclaration:
477             case XmlNodeType.ProcessingInstruction:
478                 rTW.Write("<?" + this._strName + " " + this._strValue + "?>");
479                 break;
480 
481             case XmlNodeType.Comment:
482                 rTW.Write("<!--" + this._strValue + "-->");
483                 break;
484 
485             default:
486                 throw (new Exception("Unhandled NodeType " + this._nType.ToString()));
487         }
488     }
489 
490     //
491     // Public Methods and Properties
492     //
493     public string NodeValue
494     {
495         get { return _strValue; }
496     }
497 
498     override public string Value
499     {
500         get
501         {
502             string strValue = "";
503             CXmlNode rChild;
504 
505             if ((this._eFlags & NodeFlags.HasValue) != 0)
506             {
507                 char chEnt;
508                 int nIndexAmp = 0;
509                 int nIndexSem = 0;
510 
511                 if ((this._eFlags & NodeFlags.UnparsedEntities) == 0)
512                     return this._strValue;
513 
514                 strValue = this._strValue;
515 
516                 while ((nIndexAmp = strValue.IndexOf('&', nIndexAmp)) != -1)
517                 {
518                     nIndexSem = strValue.IndexOf(';', nIndexAmp);
519                     chEnt = ResolveCharEntity(strValue.Substring(nIndexAmp + 1, nIndexSem - nIndexAmp - 1));
520                     if (chEnt != char.MinValue)
521                     {
522                         strValue = strValue.Substring(0, nIndexAmp) + chEnt + strValue.Substring(nIndexSem + 1);
523                         nIndexAmp++;
524                     }
525                     else
526                         nIndexAmp = nIndexSem;
527                 }
528                 return strValue;
529             }
530 
531             for (rChild = (CXmlNode)this._rFirstChildNode; rChild != null; rChild = (CXmlNode)rChild._rNextNode)
532             {
533                 strValue = strValue + rChild.Value;
534             }
535 
536             return strValue;
537         }
538     }
539 
540     public CXmlNode NextNode
541     {
542         get
543         {
544             CXmlBase rNode = this._rNextNode;
545 
546             while (rNode != null &&
547                    (rNode.Flags & NodeFlags.IsWhitespace) != 0)
548                 rNode = rNode._rNextNode;
549             return (CXmlNode)rNode;
550         }
551     }
552 
553     public CXmlNode FirstChild
554     {
555         get
556         {
557             CXmlBase rNode = this._rFirstChildNode;
558 
559             while (rNode != null &&
560                    (rNode.Flags & NodeFlags.IsWhitespace) != 0)
561                 rNode = rNode._rNextNode;
562             return (CXmlNode)rNode;
563         }
564     }
565 
Child(int n)566     public CXmlNode Child(int n)
567     {
568         int i;
569         CXmlNode rChild;
570 
571         i = 0;
572         for (rChild = FirstChild; rChild != null; rChild = rChild.NextNode)
573             if (i++ == n) break;
574 
575         return rChild;
576     }
577 
Child(string str)578     public CXmlNode Child(string str)
579     {
580         return (CXmlNode)base._Child(str);
581     }
582 
583     public int Type
584     {
585         get { return Convert.ToInt32(base._nType); }
586     }
587 
588     public CXmlAttribute FirstAttribute
589     {
590         get { return _rFirstAttribute; }
591     }
592 
593     public int AttributeCount
594     {
595         get { return _nAttributeCount; }
596     }
597 
Attribute(int n)598     public CXmlAttribute Attribute(int n)
599     {
600         int i;
601         CXmlAttribute rAttribute;
602 
603         i = 0;
604         for (rAttribute = _rFirstAttribute; rAttribute != null; rAttribute = rAttribute.NextAttribute)
605             if (i++ == n) break;
606         return rAttribute;
607     }
608 
Attribute(string str)609     public CXmlAttribute Attribute(string str)
610     {
611         CXmlAttribute rAttribute;
612 
613         for (rAttribute = _rFirstAttribute; rAttribute != null; rAttribute = rAttribute.NextAttribute)
614         {
615             if (rAttribute.Name == str) break;
616         }
617 
618         return rAttribute;
619     }
620 
AddAttribute(CXmlAttribute rAttribute)621     public void AddAttribute(CXmlAttribute rAttribute)
622     {
623         if (_rFirstAttribute == null)
624         {
625             _rFirstAttribute = rAttribute;
626         }
627         else
628         {
629             _rLastAttribute._rNextNode = rAttribute;
630         }
631         _rLastAttribute = rAttribute;
632         _nAttributeCount++;
633     }
634 
ResolveCharEntity(string strName)635     private char ResolveCharEntity(string strName)
636     {
637         if (strName[0] == '#')
638             if (strName[1] == 'x')
639                 return Convert.ToChar(Convert.ToInt32(strName.Substring(2), 16));
640             else
641                 return Convert.ToChar(Convert.ToInt32(strName.Substring(1)));
642         if (strName == "lt")
643             return '<';
644         if (strName == "gt")
645             return '>';
646         if (strName == "amp")
647             return '&';
648         if (strName == "apos")
649             return '\'';
650         if (strName == "quot")
651             return '"';
652 
653         return char.MinValue;
654     }
655 }
656 
657 public class CXmlCache
658 {
659     //CXmlCache Properties
660     private bool _fTrace = false;
661 
662     private bool _fThrow = true;
663     private bool _fReadNode = true;
664     private int _hr = 0;
665     private Encoding _eEncoding = System.Text.Encoding.UTF8;
666     private string _strParseError = "";
667 
668     //XmlReader Properties
669 #pragma warning disable 0618
670     private ValidationType _eValidationMode = ValidationType.Auto;
671 #pragma warning restore 0618
672 
673     private WhitespaceHandling _eWhitespaceMode = WhitespaceHandling.None;
674     private EntityHandling _eEntityMode = EntityHandling.ExpandEntities;
675     private bool _fNamespaces = true;
676 
677     private bool _fValidationCallback = false;
678     private bool _fExpandAttributeValues = false;
679 
680     //Internal stuff
681     protected XmlReader _rXmlReader = null;
682 
683     protected CXmlNode _rDocumentRootNode;
684     protected CXmlNode _rRootNode = null;
685     internal static NodeFlags _eDefaultFlags = NodeFlags.None;
686 
687     private ITestOutputHelper _output;
CXmlCache(ITestOutputHelper output)688     public CXmlCache(ITestOutputHelper output)
689     {
690         _output = output;
691     }
692 
693     //
694     // Constructor
695     //
CXmlCache()696     public CXmlCache()
697     {
698     }
699 
700     //
701     // Public Methods and Properties
702     //
Load(XmlReader rXmlReader)703     public virtual bool Load(XmlReader rXmlReader)
704     {
705         //Hook up your reader as my reader
706         _rXmlReader = rXmlReader;
707 
708         if (rXmlReader is XmlTextReader)
709         {
710             _eWhitespaceMode = ((XmlTextReader)rXmlReader).WhitespaceHandling;
711             _fNamespaces = ((XmlTextReader)rXmlReader).Namespaces;
712             _eValidationMode = ValidationType.None;
713         }
714 #pragma warning disable 0618
715         if (rXmlReader is XmlValidatingReader)
716         {
717             if (((XmlValidatingReader)rXmlReader).Reader is XmlTextReader)
718             {
719                 _eWhitespaceMode = ((XmlTextReader)((XmlValidatingReader)rXmlReader).Reader).WhitespaceHandling;
720             }
721             else
722             {
723                 _eWhitespaceMode = WhitespaceHandling.None;
724             }
725             _fNamespaces = ((XmlValidatingReader)rXmlReader).Namespaces;
726             _eValidationMode = ((XmlValidatingReader)rXmlReader).ValidationType;
727             _eEntityMode = ((XmlValidatingReader)rXmlReader).EntityHandling;
728         }
729 #pragma warning restore 0618
730 
731         DebugTrace("Setting ValidationMode=" + _eValidationMode.ToString());
732         DebugTrace("Setting EntityMode=" + _eEntityMode.ToString());
733         DebugTrace("Setting WhitespaceMode=" + _eWhitespaceMode.ToString());
734 
735         //Process the Document
736         try
737         {
738             _rDocumentRootNode = new CXmlNode("", "", XmlNodeType.Element);
739             _rDocumentRootNode._eFlags = NodeFlags.DocumentRoot | NodeFlags.Indent;
740             Process(_rDocumentRootNode);
741             for (_rRootNode = _rDocumentRootNode.FirstChild; _rRootNode != null && _rRootNode.NodeType != XmlNodeType.Element; _rRootNode = _rRootNode.NextNode) ;
742         }
743         catch (Exception e)
744         {
745             //Unhook your reader
746             _rXmlReader = null;
747 
748             _strParseError = e.ToString();
749 
750             if (_fThrow)
751             {
752                 throw (e);
753             }
754 
755             if (_hr == 0)
756                 _hr = -1;
757 
758             return false;
759         }
760 
761         //Unhook your reader
762         _rXmlReader = null;
763 
764         return true;
765     }
766 
Load(string strFileName)767     public bool Load(string strFileName)
768     {
769 #pragma warning disable 0618
770         XmlTextReader rXmlTextReader;
771         XmlValidatingReader rXmlValidatingReader;
772         bool fRet;
773 
774         rXmlTextReader = new XmlTextReader(strFileName);
775         rXmlTextReader.WhitespaceHandling = _eWhitespaceMode;
776         rXmlTextReader.Namespaces = _fNamespaces;
777 
778         _eEncoding = rXmlTextReader.Encoding;
779 
780         rXmlValidatingReader = new XmlValidatingReader(rXmlTextReader);
781         rXmlValidatingReader.ValidationType = _eValidationMode;
782         rXmlValidatingReader.EntityHandling = _eEntityMode;
783 #pragma warning restore 0618
784 
785         if (_fValidationCallback)
786             rXmlValidatingReader.ValidationEventHandler += new ValidationEventHandler(this.ValidationCallback);
787 
788         try
789         {
790             fRet = Load((XmlReader)rXmlValidatingReader);
791         }
792         catch (Exception e)
793         {
794             fRet = false;
795             rXmlValidatingReader.Dispose();
796             rXmlTextReader.Dispose();
797 
798             if (_strParseError == string.Empty)
799                 _strParseError = e.ToString();
800 
801             if (_fThrow)
802                 throw (e);
803         }
804 
805         rXmlValidatingReader.Dispose();
806         rXmlTextReader.Dispose();
807         return fRet;
808     }
809 
Save(string strName)810     public void Save(string strName)
811     {
812         Save(strName, false, _eEncoding);
813     }
814 
Save(string strName, bool fOverWrite)815     public void Save(string strName, bool fOverWrite)
816     {
817         Save(strName, fOverWrite, _eEncoding);
818     }
819 
Save(string strName, bool fOverWrite, System.Text.Encoding Encoding)820     public void Save(string strName, bool fOverWrite, System.Text.Encoding Encoding)
821     {
822         CXmlBase rNode;
823         XmlTextWriter rXmlTextWriter = null;
824 
825         try
826         {
827             if (fOverWrite)
828             {
829                 File.Delete(strName);
830             }
831 
832             rXmlTextWriter = new XmlTextWriter(strName, Encoding);
833             rXmlTextWriter.Namespaces = _fNamespaces;
834 
835             for (rNode = _rDocumentRootNode._rFirstChildNode; rNode != null; rNode = rNode._rNextNode)
836             {
837                 rNode.Write(rXmlTextWriter);
838             }
839             rXmlTextWriter.Dispose();
840         }
841         catch (Exception e)
842         {
843             DebugTrace(e.ToString());
844             if (rXmlTextWriter != null)
845                 rXmlTextWriter.Dispose();
846             throw (e);
847         }
848     }
849 
WriteXml(TextWriter rTW)850     public void WriteXml(TextWriter rTW)
851     {
852         CXmlBase rNode;
853 
854         //Spit out the document
855         for (rNode = _rDocumentRootNode._rFirstChildNode; rNode != null; rNode = rNode._rNextNode)
856             rNode.WriteXml(rTW);
857     }
858 
859     public CXmlNode RootNode
860     {
861         get { return _rRootNode; }
862     }
863 
864     public string ParseError
865     {
866         get { return _strParseError; }
867     }
868 
869     public int ParseErrorCode
870     {
871         get { return _hr; }
872     }
873 
874     //
875     // XmlReader Properties
876     //
877     public string EntityMode
878     {
879         set
880         {
881             if (value == "ExpandEntities")
882                 _eEntityMode = EntityHandling.ExpandEntities;
883             else if (value == "ExpandCharEntities")
884                 _eEntityMode = EntityHandling.ExpandCharEntities;
885             else
886                 throw (new Exception("Invalid Entity mode."));
887         }
888         get { return _eEntityMode.ToString(); }
889     }
890 
891     public string ValidationMode
892     {
893         set
894         {
895 #pragma warning disable 0618
896             if (value == "None")
897                 _eValidationMode = ValidationType.None;
898             else if (value == "DTD")
899                 _eValidationMode = ValidationType.DTD;
900             else if (value == "XDR")
901                 _eValidationMode = ValidationType.XDR;
902             else if (value == "Schema")
903                 _eValidationMode = ValidationType.Schema;
904             else if (value == "Auto")
905                 _eValidationMode = ValidationType.Auto;
906             else
907                 throw (new Exception("Invalid Validation mode."));
908 #pragma warning restore 0618
909         }
910         get { return _eValidationMode.ToString(); }
911     }
912 
913     public string WhitespaceMode
914     {
915         set
916         {
917             if (value == "All")
918                 _eWhitespaceMode = WhitespaceHandling.All;
919             else if (value == "Significant")
920                 _eWhitespaceMode = WhitespaceHandling.Significant;
921             else if (value == "None")
922                 _eWhitespaceMode = WhitespaceHandling.None;
923             else
924                 throw (new Exception("Invalid Whitespace mode."));
925         }
926         get { return _eWhitespaceMode.ToString(); }
927     }
928 
929     public bool Namespaces
930     {
931         set { _fNamespaces = value; }
932         get { return _fNamespaces; }
933     }
934 
935     public bool UseValidationCallback
936     {
937         set { _fValidationCallback = value; }
938         get { return _fValidationCallback; }
939     }
940 
941     public bool ExpandAttributeValues
942     {
943         set { _fExpandAttributeValues = value; }
944         get { return _fExpandAttributeValues; }
945     }
946 
947     //
948     // Internal Properties
949     //
950     public bool Throw
951     {
952         get { return _fThrow; }
953         set { _fThrow = value; }
954     }
955 
956     public bool Trace
957     {
958         set { _fTrace = value; }
959         get { return _fTrace; }
960     }
961 
962     //
963     //Private Methods
964     //
DebugTrace(string str)965     private void DebugTrace(string str)
966     {
967         DebugTrace(str, 0);
968     }
969 
DebugTrace(string str, int nDepth)970     private void DebugTrace(string str, int nDepth)
971     {
972         if (_fTrace)
973         {
974             int i;
975 
976             for (i = 0; i < nDepth; i++)
977                 _output.WriteLine(" ");
978             _output.WriteLine(str);
979         }
980     }
981 
DebugTrace(XmlReader rXmlReader)982     private void DebugTrace(XmlReader rXmlReader)
983     {
984         if (_fTrace)
985         {
986             string str;
987 
988             str = rXmlReader.NodeType.ToString() + ", Depth=" + rXmlReader.Depth + " Name=";
989             if (rXmlReader.Prefix != "")
990             {
991                 str += rXmlReader.Prefix + ":";
992             }
993             str += rXmlReader.LocalName;
994 
995             if (rXmlReader.HasValue)
996                 str += " Value=" + rXmlReader.Value;
997 
998             if (rXmlReader.NodeType == XmlNodeType.Attribute)
999                 str += " QuoteChar=" + rXmlReader.QuoteChar;
1000 
1001             DebugTrace(str, rXmlReader.Depth);
1002         }
1003     }
1004 
Process(CXmlBase rParentNode)1005     protected void Process(CXmlBase rParentNode)
1006     {
1007         CXmlNode rNewNode;
1008 
1009         while (true)
1010         {
1011             //We want to pop if Read() returns false, aka EOF
1012             if (_fReadNode)
1013             {
1014                 if (!_rXmlReader.Read())
1015                 {
1016                     DebugTrace("Read() == false");
1017                     return;
1018                 }
1019             }
1020             else
1021             {
1022                 if (!_rXmlReader.ReadAttributeValue())
1023                 {
1024                     DebugTrace("ReadAttributeValue() == false");
1025                     return;
1026                 }
1027             }
1028 
1029             DebugTrace(_rXmlReader);
1030 
1031             //We also want to pop if we get an EndElement or EndEntity
1032             if (_rXmlReader.NodeType == XmlNodeType.EndElement ||
1033                  _rXmlReader.NodeType == XmlNodeType.EndEntity)
1034             {
1035                 DebugTrace("NodeType == EndElement or EndEntity");
1036                 return;
1037             }
1038 
1039             rNewNode = GetNewNode(_rXmlReader);
1040             rNewNode._nDepth = _rXmlReader.Depth;
1041 
1042             // Test for MixedContent and set Indent if necessary
1043             if ((rParentNode.Flags & NodeFlags.MixedContent) != 0)
1044             {
1045                 rNewNode._eFlags |= NodeFlags.MixedContent;
1046                 // Indent is off for all new nodes
1047             }
1048             else
1049             {
1050                 rNewNode._eFlags |= NodeFlags.Indent;		// Turn on Indent for current Node
1051             }
1052 
1053             // Set all Depth 0 nodes to No Mixed Content and Indent True
1054             if (_rXmlReader.Depth == 0)
1055             {
1056                 rNewNode._eFlags |= NodeFlags.Indent;			// Turn on Indent
1057                 rNewNode._eFlags &= ~NodeFlags.MixedContent;	// Turn off MixedContent
1058             }
1059 
1060             rParentNode.InsertNode(rNewNode);
1061 
1062             //Do some special stuff based on NodeType
1063             switch (_rXmlReader.NodeType)
1064             {
1065                 case XmlNodeType.EntityReference:
1066                     if (_eValidationMode == ValidationType.DTD)
1067                     {
1068                         _rXmlReader.ResolveEntity();
1069                         Process(rNewNode);
1070                     }
1071                     break;
1072 
1073                 case XmlNodeType.Element:
1074                     if (_rXmlReader.MoveToFirstAttribute())
1075                     {
1076                         do
1077                         {
1078                             CXmlAttribute rNewAttribute = new CXmlAttribute(_rXmlReader);
1079                             rNewNode.AddAttribute(rNewAttribute);
1080 
1081                             if (_fExpandAttributeValues)
1082                             {
1083                                 DebugTrace("Attribute: " + _rXmlReader.Name);
1084                                 _fReadNode = false;
1085                                 Process(rNewAttribute);
1086                                 _fReadNode = true;
1087                             }
1088                             else
1089                             {
1090                                 CXmlNode rValueNode = new CXmlNode("", "", XmlNodeType.Text);
1091                                 rValueNode._eFlags = _eDefaultFlags | NodeFlags.HasValue;
1092 
1093                                 rValueNode._strValue = _rXmlReader.Value;
1094 
1095                                 DebugTrace("  Value=" + rValueNode.Value, _rXmlReader.Depth + 1);
1096 
1097                                 rNewAttribute.InsertNode(rValueNode);
1098                             }
1099                         } while (_rXmlReader.MoveToNextAttribute());
1100                     }
1101 
1102                     if ((rNewNode.Flags & NodeFlags.EmptyElement) == 0)
1103                         Process(rNewNode);
1104 
1105                     break;
1106 
1107                 case XmlNodeType.XmlDeclaration:
1108                     if (_rXmlReader is XmlTextReader)
1109                     {
1110                         _eEncoding = ((XmlTextReader)_rXmlReader).Encoding;
1111                     }
1112 #pragma warning disable 0618
1113                     else if (_rXmlReader is XmlValidatingReader)
1114                     {
1115                         _eEncoding = ((XmlValidatingReader)_rXmlReader).Encoding;
1116                     }
1117 #pragma warning restore 0618
1118                     else
1119                     {
1120                         string strValue = rNewNode.NodeValue;
1121                         int nPos = strValue.IndexOf("encoding");
1122                         if (nPos != -1)
1123                         {
1124                             int nEnd;
1125 
1126                             nPos = strValue.IndexOf("=", nPos);			//Find the = sign
1127                             nEnd = strValue.IndexOf("\"", nPos) + 1;	//Find the next " character
1128                             nPos = strValue.IndexOf("'", nPos) + 1;		//Find the next ' character
1129                             if (nEnd == 0 || (nPos < nEnd && nPos > 0))	//Pick the one that's closer to the = sign
1130                             {
1131                                 nEnd = strValue.IndexOf("'", nPos);
1132                             }
1133                             else
1134                             {
1135                                 nPos = nEnd;
1136                                 nEnd = strValue.IndexOf("\"", nPos);
1137                             }
1138                             string sEncodeName = strValue.Substring(nPos, nEnd - nPos);
1139                             DebugTrace("XMLDecl contains encoding " + sEncodeName);
1140                             if (sEncodeName.ToUpper() == "UCS-2")
1141                             {
1142                                 sEncodeName = "unicode";
1143                             }
1144                             _eEncoding = System.Text.Encoding.GetEncoding(sEncodeName);
1145                         }
1146                     }
1147                     break;
1148 
1149                 case XmlNodeType.ProcessingInstruction:
1150                     break;
1151 
1152                 case XmlNodeType.Text:
1153                     if (!_fReadNode)
1154                     {
1155                         rNewNode._eFlags = _eDefaultFlags | NodeFlags.AttributeTextNode;
1156                     }
1157                     rNewNode._eFlags |= NodeFlags.MixedContent;		// turn on Mixed Content for current node
1158                     rNewNode._eFlags &= ~NodeFlags.Indent;			// turn off Indent for current node
1159                     rParentNode._eFlags |= NodeFlags.MixedContent;	// turn on Mixed Content for Parent Node
1160                     break;
1161 
1162                 case XmlNodeType.Whitespace:
1163                 case XmlNodeType.SignificantWhitespace:
1164                 case XmlNodeType.CDATA:
1165                     rNewNode._eFlags |= NodeFlags.MixedContent;		// turn on Mixed Content for current node
1166                     rNewNode._eFlags &= ~NodeFlags.Indent;			// turn off Indent for current node
1167                     rParentNode._eFlags |= NodeFlags.MixedContent;	// turn on Mixed Content for Parent Node
1168                     break;
1169 
1170                 case XmlNodeType.Comment:
1171                 case XmlNodeType.Notation:
1172                     break;
1173 
1174                 case XmlNodeType.DocumentType:
1175                     if (_rXmlReader.MoveToFirstAttribute())
1176                     {
1177                         do
1178                         {
1179                             CXmlAttribute rNewAttribute = new CXmlAttribute(_rXmlReader);
1180                             rNewNode.AddAttribute(rNewAttribute);
1181 
1182                             CXmlNode rValueNode = new CXmlNode(_rXmlReader);
1183                             rValueNode._strValue = _rXmlReader.Value;
1184                             rNewAttribute.InsertNode(rValueNode);
1185                         } while (_rXmlReader.MoveToNextAttribute());
1186                     }
1187 
1188                     break;
1189 
1190                 default:
1191                     _output.WriteLine("UNHANDLED TYPE, " + _rXmlReader.NodeType.ToString() + " IN Process()!");
1192                     break;
1193             }
1194         }
1195     }
1196 
GetNewNode(XmlReader rXmlReader)1197     protected virtual CXmlNode GetNewNode(XmlReader rXmlReader)
1198     {
1199         return new CXmlNode(rXmlReader);
1200     }
1201 
ValidationCallback(object sender, ValidationEventArgs args)1202     private void ValidationCallback(object sender, ValidationEventArgs args)
1203     {
1204         //  commented by ROCHOA -- don't know where ValidationEventArgs comes from
1205         //	_hr = Convert.ToInt16(args.ErrorCode);
1206         throw (new Exception("[" + Convert.ToString(_hr) + "] " + args.Message));
1207     }
1208 }
1209 
1210 public class ChecksumWriter : TextWriter
1211 {
1212     private int _nPosition = 0;
1213     private Decimal _dResult = 0;
1214     private Encoding _encoding;
1215 
1216     // --------------------------------------------------------------------------------------------------
1217     //    Constructor
1218     // --------------------------------------------------------------------------------------------------
ChecksumWriter()1219     public ChecksumWriter()
1220     {
1221         _encoding = Encoding.UTF8;
1222     }
1223 
1224     // --------------------------------------------------------------------------------------------------
1225     //    Properties
1226     // --------------------------------------------------------------------------------------------------
1227     public Decimal CheckSum
1228     {
1229         get { return _dResult; }
1230     }
1231 
1232     public override Encoding Encoding
1233     {
1234         get { return _encoding; }
1235     }
1236 
1237     // --------------------------------------------------------------------------------------------------
1238     //    Public methods
1239     // --------------------------------------------------------------------------------------------------
Write(String str)1240     override public void Write(String str)
1241     {
1242         int i;
1243         int m;
1244 
1245         m = str.Length;
1246         for (i = 0; i < m; i++)
1247         {
1248             Write(str[i]);
1249         }
1250     }
1251 
Write(Char[] rgch)1252     override public void Write(Char[] rgch)
1253     {
1254         int i;
1255         int m;
1256 
1257         m = rgch.Length;
1258         for (i = 0; i < m; i++)
1259         {
1260             Write(rgch[i]);
1261         }
1262     }
1263 
Write(Char[] rgch, Int32 iOffset, Int32 iCount)1264     override public void Write(Char[] rgch, Int32 iOffset, Int32 iCount)
1265     {
1266         int i;
1267         int m;
1268 
1269         m = iOffset + iCount;
1270         for (i = iOffset; i < m; i++)
1271         {
1272             Write(rgch[i]);
1273         }
1274     }
1275 
Write(Char ch)1276     override public void Write(Char ch)
1277     {
1278         _dResult += Math.Round((Decimal)(ch / (_nPosition + 1.0)), 10);
1279         _nPosition++;
1280     }
1281 
Close()1282     override public void Close()
1283     {
1284         _nPosition = 0;
1285         _dResult = 0;
1286     }
1287 }
1288