The Labs \ Source Viewer \ SSCLI \ System.Xml.Schema \ Parser

  1. //------------------------------------------------------------------------------
  2. // <copyright file="Parser.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. // <owner current="true" primary="true">priyal</owner>
  15. //------------------------------------------------------------------------------
  16. namespace System.Xml.Schema
  17. {
  18.    
  19.     using System;
  20.     using System.Collections;
  21.     using System.Globalization;
  22.     using System.Text;
  23.     using System.IO;
  24.     using System.Diagnostics;
  25.    
  26.     internal sealed class Parser
  27.     {
  28.        
  29.         SchemaType schemaType;
  30.         XmlNameTable nameTable;
  31.         SchemaNames schemaNames;
  32.         ValidationEventHandler eventHandler;
  33.         XmlNamespaceManager namespaceManager;
  34.         XmlReader reader;
  35.         PositionInfo positionInfo;
  36.         bool isProcessNamespaces;
  37.         int schemaXmlDepth = 0;
  38.         int markupDepth;
  39.         SchemaBuilder builder;
  40.         XmlSchema schema;
  41.         SchemaInfo xdrSchema;
  42.         XmlResolver xmlResolver = null;
  43.         //to be used only by XDRBuilder
  44.         //xs:Annotation perf fix
  45.         XmlDocument dummyDocument;
  46.         bool processMarkup;
  47.         XmlNode parentNode;
  48.         XmlNamespaceManager annotationNSManager;
  49.         string xmlns;
  50.        
  51.         public Parser(SchemaType schemaType, XmlNameTable nameTable, SchemaNames schemaNames, ValidationEventHandler eventHandler)
  52.         {
  53.             this.schemaType = schemaType;
  54.             this.nameTable = nameTable;
  55.             this.schemaNames = schemaNames;
  56.             this.eventHandler = eventHandler;
  57.             this.xmlResolver = new XmlUrlResolver();
  58.             processMarkup = true;
  59.             dummyDocument = new XmlDocument();
  60.         }
  61.        
  62.         public SchemaType Parse(XmlReader reader, string targetNamespace)
  63.         {
  64.             StartParsing(reader, targetNamespace);
  65.             while (ParseReaderNode() && reader.Read()) {
  66.             }
  67.             return FinishParsing();
  68.         }
  69.        
  70.         public void StartParsing(XmlReader reader, string targetNamespace)
  71.         {
  72.             this.reader = reader;
  73.             positionInfo = PositionInfo.GetPositionInfo(reader);
  74.             namespaceManager = reader.NamespaceManager;
  75.             if (namespaceManager == null) {
  76.                 namespaceManager = new XmlNamespaceManager(nameTable);
  77.                 isProcessNamespaces = true;
  78.             }
  79.             else {
  80.                 isProcessNamespaces = false;
  81.             }
  82.             while (reader.NodeType != XmlNodeType.Element && reader.Read()) {
  83.             }
  84.            
  85.             markupDepth = int.MaxValue;
  86.             schemaXmlDepth = reader.Depth;
  87.             SchemaType rootType = schemaNames.SchemaTypeFromRoot(reader.LocalName, reader.NamespaceURI);
  88.            
  89.             string code;
  90.             if (!CheckSchemaRoot(rootType, out code)) {
  91.                 throw new XmlSchemaException(code, reader.BaseURI, positionInfo.LineNumber, positionInfo.LinePosition);
  92.             }
  93.            
  94.             if (schemaType == SchemaType.XSD) {
  95.                 schema = new XmlSchema();
  96.                 schema.BaseUri = new Uri(reader.BaseURI, UriKind.RelativeOrAbsolute);
  97.                 builder = new XsdBuilder(reader, namespaceManager, schema, nameTable, schemaNames, eventHandler);
  98.             }
  99.             else {
  100.                 Debug.Assert(schemaType == SchemaType.XDR);
  101.                 xdrSchema = new SchemaInfo();
  102.                 xdrSchema.SchemaType = SchemaType.XDR;
  103.                 builder = new XdrBuilder(reader, namespaceManager, xdrSchema, targetNamespace, nameTable, schemaNames, eventHandler);
  104.                 ((XdrBuilder)builder).XmlResolver = xmlResolver;
  105.             }
  106.         }
  107.        
  108.         private bool CheckSchemaRoot(SchemaType rootType, out string code)
  109.         {
  110.             code = null;
  111.             if (schemaType == SchemaType.None) {
  112.                 schemaType = rootType;
  113.             }
  114.             switch (rootType) {
  115.                 case SchemaType.XSD:
  116.                     if (schemaType != SchemaType.XSD) {
  117.                         code = Res.Sch_MixSchemaTypes;
  118.                         return false;
  119.                     }
  120.                     break;
  121.                 case SchemaType.XDR:
  122.                    
  123.                     if (schemaType == SchemaType.XSD) {
  124.                         code = Res.Sch_XSDSchemaOnly;
  125.                         return false;
  126.                     }
  127.                     else if (schemaType != SchemaType.XDR) {
  128.                         code = Res.Sch_MixSchemaTypes;
  129.                         return false;
  130.                     }
  131.                     break;
  132.                 case SchemaType.DTD:
  133.                 case SchemaType.None:
  134.                    
  135.                     //Did not detect schema type that can be parsed by this parser
  136.                     code = Res.Sch_SchemaRootExpected;
  137.                     if (schemaType == SchemaType.XSD) {
  138.                         code = Res.Sch_XSDSchemaRootExpected;
  139.                     }
  140.                     return false;
  141.                 default:
  142.                    
  143.                     Debug.Assert(false);
  144.                     break;
  145.             }
  146.             return true;
  147.         }
  148.        
  149.         public SchemaType FinishParsing()
  150.         {
  151.             return schemaType;
  152.         }
  153.        
  154.         public XmlSchema XmlSchema {
  155.             get { return schema; }
  156.         }
  157.        
  158.         internal XmlResolver XmlResolver {
  159.             set { xmlResolver = value; }
  160.         }
  161.        
  162.         public SchemaInfo XdrSchema {
  163.             get { return xdrSchema; }
  164.         }
  165.        
  166.        
  167.         public bool ParseReaderNode()
  168.         {
  169.             if (reader.Depth > markupDepth) {
  170.                 if (processMarkup) {
  171.                     ProcessAppInfoDocMarkup(false);
  172.                 }
  173.                 return true;
  174.             }
  175.             else if (reader.NodeType == XmlNodeType.Element) {
  176.                 if (builder.ProcessElement(reader.Prefix, reader.LocalName, reader.NamespaceURI)) {
  177.                     namespaceManager.PushScope();
  178.                     if (reader.MoveToFirstAttribute()) {
  179.                         do {
  180.                             builder.ProcessAttribute(reader.Prefix, reader.LocalName, reader.NamespaceURI, reader.Value);
  181.                             if (Ref.Equal(reader.NamespaceURI, schemaNames.NsXmlNs) && isProcessNamespaces) {
  182.                                 namespaceManager.AddNamespace(reader.Prefix.Length == 0 ? string.Empty : reader.LocalName, reader.Value);
  183.                             }
  184.                         }
  185.                         while (reader.MoveToNextAttribute());
  186.                         reader.MoveToElement();
  187.                         // get back to the element
  188.                     }
  189.                     builder.StartChildren();
  190.                     if (reader.IsEmptyElement) {
  191.                         namespaceManager.PopScope();
  192.                         builder.EndChildren();
  193.                     }
  194.                     else if (!builder.IsContentParsed()) {
  195.                         //AppInfo and Documentation
  196.                         markupDepth = reader.Depth;
  197.                         processMarkup = true;
  198.                         if (annotationNSManager == null) {
  199.                             annotationNSManager = new XmlNamespaceManager(nameTable);
  200.                             xmlns = nameTable.Add("xmlns");
  201.                         }
  202.                         ProcessAppInfoDocMarkup(true);
  203.                     }
  204.                 }
  205.                 else if (!reader.IsEmptyElement) {
  206.                     //UnsupportedElement in that context
  207.                     markupDepth = reader.Depth;
  208.                     processMarkup = false;
  209.                     //Hack to not process unsupported elements
  210.                 }
  211.             }
  212.             else if (reader.NodeType == XmlNodeType.Text || reader.NodeType == XmlNodeType.EntityReference || reader.NodeType == XmlNodeType.SignificantWhitespace || reader.NodeType == XmlNodeType.CDATA) {
  213.                 builder.ProcessCData(reader.Value);
  214.             }
  215.             else if (reader.NodeType == XmlNodeType.EndElement) {
  216.                
  217.                 if (reader.Depth == markupDepth) {
  218.                     if (processMarkup) {
  219.                         Debug.Assert(parentNode != null);
  220.                         XmlNodeList list = parentNode.ChildNodes;
  221.                         XmlNode[] markup = new XmlNode[list.Count];
  222.                         for (int i = 0; i < list.Count; i++) {
  223.                             markup[i] = list[i];
  224.                         }
  225.                         builder.ProcessMarkup(markup);
  226.                         namespaceManager.PopScope();
  227.                         builder.EndChildren();
  228.                     }
  229.                     markupDepth = int.MaxValue;
  230.                 }
  231.                 else {
  232.                     namespaceManager.PopScope();
  233.                     builder.EndChildren();
  234.                 }
  235.                 if (reader.Depth == schemaXmlDepth) {
  236.                     return false;
  237.                     // done
  238.                 }
  239.             }
  240.             return true;
  241.         }
  242.        
  243.        
  244.         private void ProcessAppInfoDocMarkup(bool root)
  245.         {
  246.             //First time reader is positioned on AppInfo or Documentation element
  247.             XmlNode currentNode = null;
  248.            
  249.             switch (reader.NodeType) {
  250.                 case XmlNodeType.Element:
  251.                     annotationNSManager.PushScope();
  252.                     currentNode = LoadElementNode(root);
  253.                     break;
  254.                 case XmlNodeType.Text:
  255.                    
  256.                     currentNode = dummyDocument.CreateTextNode(reader.Value);
  257.                     goto default;
  258.                     break;
  259.                 case XmlNodeType.SignificantWhitespace:
  260.                    
  261.                     currentNode = dummyDocument.CreateSignificantWhitespace(reader.Value);
  262.                     goto default;
  263.                     break;
  264.                 case XmlNodeType.CDATA:
  265.                    
  266.                     currentNode = dummyDocument.CreateCDataSection(reader.Value);
  267.                     goto default;
  268.                     break;
  269.                 case XmlNodeType.EntityReference:
  270.                    
  271.                     currentNode = dummyDocument.CreateEntityReference(reader.Name);
  272.                     goto default;
  273.                     break;
  274.                 case XmlNodeType.Comment:
  275.                    
  276.                     currentNode = dummyDocument.CreateComment(reader.Value);
  277.                     goto default;
  278.                     break;
  279.                 case XmlNodeType.ProcessingInstruction:
  280.                    
  281.                     currentNode = dummyDocument.CreateProcessingInstruction(reader.Name, reader.Value);
  282.                     goto default;
  283.                     break;
  284.                 case XmlNodeType.EndEntity:
  285.                    
  286.                     break;
  287.                 case XmlNodeType.Whitespace:
  288.                    
  289.                     break;
  290.                 case XmlNodeType.EndElement:
  291.                    
  292.                     annotationNSManager.PopScope();
  293.                     parentNode = parentNode.ParentNode;
  294.                     break;
  295.                 default:
  296.                    
  297.                     //other possible node types: Document/DocType/DocumentFrag/Entity/Notation/Xmldecl cannot appear as children of xs:appInfo or xs:doc
  298.                     Debug.Assert(currentNode != null);
  299.                     Debug.Assert(parentNode != null);
  300.                     parentNode.AppendChild(currentNode);
  301.                     break;
  302.             }
  303.         }
  304.        
  305.         private XmlElement LoadElementNode(bool root)
  306.         {
  307.             Debug.Assert(reader.NodeType == XmlNodeType.Element);
  308.            
  309.             XmlReader r = reader;
  310.             bool fEmptyElement = r.IsEmptyElement;
  311.            
  312.             XmlElement element = dummyDocument.CreateElement(r.Prefix, r.LocalName, r.NamespaceURI);
  313.             element.IsEmpty = fEmptyElement;
  314.            
  315.             if (root) {
  316.                 parentNode = element;
  317.             }
  318.             else {
  319.                 XmlAttributeCollection attributes = element.Attributes;
  320.                 if (r.MoveToFirstAttribute()) {
  321.                     do {
  322.                         if (Ref.Equal(r.NamespaceURI, schemaNames.NsXmlNs)) {
  323.                             //Namespace Attribute
  324.                             annotationNSManager.AddNamespace(r.Prefix.Length == 0 ? string.Empty : reader.LocalName, reader.Value);
  325.                         }
  326.                         XmlAttribute attr = LoadAttributeNode();
  327.                         attributes.Append(attr);
  328.                     }
  329.                     while (r.MoveToNextAttribute());
  330.                 }
  331.                 r.MoveToElement();
  332.                 string ns = annotationNSManager.LookupNamespace(r.Prefix);
  333.                 if (ns == null) {
  334.                     XmlAttribute attr = CreateXmlNsAttribute(r.Prefix, namespaceManager.LookupNamespace(r.Prefix));
  335.                     attributes.Append(attr);
  336.                 }
  337.                 else if (ns.Length == 0) {
  338.                     //string.Empty prefix is mapped to string.Empty NS by default
  339.                     string elemNS = namespaceManager.LookupNamespace(r.Prefix);
  340.                     if (elemNS != string.Empty) {
  341.                         XmlAttribute attr = CreateXmlNsAttribute(r.Prefix, elemNS);
  342.                         attributes.Append(attr);
  343.                     }
  344.                 }
  345.                
  346.                 while (r.MoveToNextAttribute()) {
  347.                     if (r.Prefix.Length != 0) {
  348.                         string attNS = annotationNSManager.LookupNamespace(r.Prefix);
  349.                         if (attNS == null) {
  350.                             XmlAttribute attr = CreateXmlNsAttribute(r.Prefix, namespaceManager.LookupNamespace(r.Prefix));
  351.                             attributes.Append(attr);
  352.                         }
  353.                     }
  354.                 }
  355.                 r.MoveToElement();
  356.                
  357.                 parentNode.AppendChild(element);
  358.                 if (!r.IsEmptyElement) {
  359.                     parentNode = element;
  360.                 }
  361.             }
  362.             return element;
  363.         }
  364.        
  365.        
  366.         private XmlAttribute CreateXmlNsAttribute(string prefix, string value)
  367.         {
  368.             XmlAttribute attr;
  369.             if (prefix.Length == 0) {
  370.                 attr = dummyDocument.CreateAttribute(string.Empty, xmlns, XmlReservedNs.NsXmlNs);
  371.             }
  372.             else {
  373.                 attr = dummyDocument.CreateAttribute(xmlns, prefix, XmlReservedNs.NsXmlNs);
  374.             }
  375.             attr.AppendChild(dummyDocument.CreateTextNode(value));
  376.             annotationNSManager.AddNamespace(prefix, value);
  377.             return attr;
  378.         }
  379.        
  380.         private XmlAttribute LoadAttributeNode()
  381.         {
  382.             Debug.Assert(reader.NodeType == XmlNodeType.Attribute);
  383.            
  384.             XmlReader r = reader;
  385.            
  386.             XmlAttribute attr = dummyDocument.CreateAttribute(r.Prefix, r.LocalName, r.NamespaceURI);
  387.            
  388.             while (r.ReadAttributeValue()) {
  389.                 switch (r.NodeType) {
  390.                     case XmlNodeType.Text:
  391.                         attr.AppendChild(dummyDocument.CreateTextNode(r.Value));
  392.                         continue;
  393.                     case XmlNodeType.EntityReference:
  394.                         attr.AppendChild(LoadEntityReferenceInAttribute());
  395.                         continue;
  396.                     default:
  397.                         throw XmlLoader.UnexpectedNodeType(r.NodeType);
  398.                         break;
  399.                 }
  400.             }
  401.            
  402.             return attr;
  403.         }
  404.        
  405.        
  406.         private XmlEntityReference LoadEntityReferenceInAttribute()
  407.         {
  408.             Debug.Assert(reader.NodeType == XmlNodeType.EntityReference);
  409.            
  410.             XmlEntityReference eref = dummyDocument.CreateEntityReference(reader.LocalName);
  411.             if (!reader.CanResolveEntity) {
  412.                 return eref;
  413.             }
  414.             reader.ResolveEntity();
  415.            
  416.             while (reader.ReadAttributeValue()) {
  417.                 switch (reader.NodeType) {
  418.                     case XmlNodeType.Text:
  419.                         eref.AppendChild(dummyDocument.CreateTextNode(reader.Value));
  420.                         continue;
  421.                     case XmlNodeType.EndEntity:
  422.                         if (eref.ChildNodes.Count == 0) {
  423.                             eref.AppendChild(dummyDocument.CreateTextNode(String.Empty));
  424.                         }
  425.                         return eref;
  426.                     case XmlNodeType.EntityReference:
  427.                         eref.AppendChild(LoadEntityReferenceInAttribute());
  428.                         break;
  429.                     default:
  430.                         throw XmlLoader.UnexpectedNodeType(reader.NodeType);
  431.                         break;
  432.                 }
  433.             }
  434.            
  435.             return eref;
  436.         }
  437.        
  438.        
  439.     }
  440.    
  441. }
  442. // namespace System.Xml

Developer Fusion