Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / XmlUtils / System / Xml / Xsl / QIL / QilXmlReader.cs / 1305376 / QilXmlReader.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //----------------------------------------------------------------------------- using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Globalization; using System.Text; using System.Text.RegularExpressions; using System.Reflection; using System.Xml; using System.Xml.Schema; using System.Xml.Xsl; namespace System.Xml.Xsl.Qil { ////// Read the output of QilXmlWriter. /// ///This internal class allows roundtripping between the Xml serialization format for /// QIL and the in-memory data structure. internal sealed class QilXmlReader { private static Regex lineInfoRegex = new Regex(@"\[(\d+),(\d+) -- (\d+),(\d+)\]"); private static Regex typeInfoRegex = new Regex(@"(\w+);([\w|\|]+);(\w+)"); private static DictionarynameToFactoryMethod; private QilFactory f; private XmlReader r; private Stack stk; private bool inFwdDecls; private Dictionary scope, fwdDecls; static QilXmlReader() { nameToFactoryMethod = new Dictionary (); // Build table that maps QilNodeType name to factory method info foreach (MethodInfo mi in typeof(QilFactory).GetMethods(BindingFlags.Public | BindingFlags.Instance)) { ParameterInfo[] parms = mi.GetParameters(); int i; // Only match methods that take QilNode parameters for (i = 0; i < parms.Length; i++) { if (parms[i].ParameterType != typeof(QilNode)) break; } if (i == parms.Length) { // Enter the method that takes the maximum number of parameters if (!nameToFactoryMethod.ContainsKey(mi.Name) || nameToFactoryMethod[mi.Name].GetParameters().Length < parms.Length) nameToFactoryMethod[mi.Name] = mi; } } } public QilXmlReader(XmlReader r) { this.r = r; this.f = new QilFactory(); } public QilExpression Read() { this.stk = new Stack (); this.inFwdDecls = false; this.scope = new Dictionary (); this.fwdDecls = new Dictionary (); this.stk.Push(f.Sequence()); while (r.Read()) { switch (r.NodeType) { case XmlNodeType.Element: bool emptyElem = r.IsEmptyElement; // XmlReader does not give an event for empty elements, so synthesize one if (StartElement() && emptyElem) EndElement(); break; case XmlNodeType.EndElement: EndElement(); break; case XmlNodeType.Whitespace: case XmlNodeType.SignificantWhitespace: case XmlNodeType.XmlDeclaration: case XmlNodeType.Comment: case XmlNodeType.ProcessingInstruction: break; default: Debug.Fail("Unexpected event " + r.NodeType + ", value " + r.Value); break; } } Debug.Assert(this.fwdDecls.Keys.Count == 0, "One or more forward declarations were never defined"); Debug.Assert(this.stk.Peek()[0].NodeType == QilNodeType.QilExpression, "Serialized qil tree did not contain a QilExpression node"); return (QilExpression) this.stk.Peek()[0]; } private bool StartElement() { QilNode nd; ReaderAnnotation ann = new ReaderAnnotation(); string s; // Special case certain element names s = r.LocalName; switch (r.LocalName) { case "LiteralString": nd = f.LiteralString(ReadText()); break; case "LiteralInt32": nd = f.LiteralInt32(Int32.Parse(ReadText(), CultureInfo.InvariantCulture)); break; case "LiteralInt64": nd = f.LiteralInt64(Int64.Parse(ReadText(), CultureInfo.InvariantCulture)); break; case "LiteralDouble": nd = f.LiteralDouble(Double.Parse(ReadText(), CultureInfo.InvariantCulture)); break; case "LiteralDecimal": nd = f.LiteralDecimal(Decimal.Parse(ReadText(), CultureInfo.InvariantCulture)); break; case "LiteralType": nd = f.LiteralType(ParseType(ReadText())); break; case "LiteralQName": nd = ParseName(r.GetAttribute("name")); Debug.Assert(nd != null, "LiteralQName element must have a name attribute"); Debug.Assert(r.IsEmptyElement, "LiteralQName element must be empty"); break; case "For": case "Let": case "Parameter": case "Function": case "RefTo": ann.Id = r.GetAttribute("id"); ann.Name = ParseName(r.GetAttribute("name")); goto default; case "XsltInvokeEarlyBound": ann.ClrNamespace = r.GetAttribute("clrNamespace"); goto default; case "ForwardDecls": this.inFwdDecls = true; goto default; default: // Create sequence nd = f.Sequence(); break; } // Save xml type and source line information ann.XmlType = ParseType(r.GetAttribute("xmlType"));; nd.SourceLine = ParseLineInfo(r.GetAttribute("lineInfo")); nd.Annotation = ann; if (nd is QilList) { // Push new parent list onto stack this.stk.Push((QilList) nd); return true; } // Add node to its parent's list this.stk.Peek().Add(nd); return false; } private void EndElement() { MethodInfo facMethod = null; object[] facArgs; QilList list; QilNode nd; ReaderAnnotation ann; list = this.stk.Pop(); ann = (ReaderAnnotation) list.Annotation; // Special case certain element names string s = r.LocalName; switch (r.LocalName) { case "QilExpression": { Debug.Assert(list.Count > 0, "QilExpression node requires a Root expression"); QilExpression qil = f.QilExpression(list[list.Count - 1]); // Be flexible on order and presence of QilExpression children for (int i = 0; i < list.Count - 1; i++) { switch (list[i].NodeType) { case QilNodeType.True: case QilNodeType.False: qil.IsDebug = list[i].NodeType == QilNodeType.True; break; case QilNodeType.FunctionList: qil.FunctionList = (QilList) list[i]; break; case QilNodeType.GlobalVariableList: qil.GlobalVariableList = (QilList) list[i]; break; case QilNodeType.GlobalParameterList: qil.GlobalParameterList = (QilList) list[i]; break; } } nd = qil; break; } case "ForwardDecls": this.inFwdDecls = false; return; case "Parameter": case "Let": case "For": case "Function": { string id = ann.Id; QilName name = ann.Name; Debug.Assert(id != null, r.LocalName + " must have an id attribute"); Debug.Assert(!this.inFwdDecls || ann.XmlType != null, "Forward decl for " + r.LocalName + " '" + id + "' must have an xmlType attribute"); // Create node (may be discarded later if it was already declared in forward declarations section) switch (r.LocalName) { case "Parameter": Debug.Assert(list.Count <= (this.inFwdDecls ? 0 : 1), "Parameter '" + id + "' must have 0 or 1 arguments"); Debug.Assert(ann.XmlType != null, "Parameter '" + id + "' must have an xmlType attribute"); if (this.inFwdDecls || list.Count == 0) nd = f.Parameter(null, name, ann.XmlType); else nd = f.Parameter(list[0], name, ann.XmlType); break; case "Let": Debug.Assert(list.Count == (this.inFwdDecls ? 0 : 1), "Let '" + id + "' must have 0 or 1 arguments"); if (this.inFwdDecls) nd = f.Let(f.Unknown(ann.XmlType)); else nd = f.Let(list[0]); break; case "For": Debug.Assert(list.Count == 1, "For '" + id + "' must have 1 argument"); nd = f.For(list[0]); break; default: Debug.Assert(list.Count == (this.inFwdDecls ? 2 : 3), "Function '" + id + "' must have 2 or 3 arguments"); if (this.inFwdDecls) nd = f.Function(list[0], list[1], ann.XmlType); else nd = f.Function(list[0], list[1], list[2], ann.XmlType != null ? ann.XmlType : list[1].XmlType); break; } // Set DebugName if (name != null) ((QilReference) nd).DebugName = name.ToString(); if (this.inFwdDecls) { Debug.Assert(!this.scope.ContainsKey(id), "Multiple nodes have id '" + id + "'"); this.fwdDecls[id] = nd; this.scope[id] = nd; } else { if (this.fwdDecls.ContainsKey(id)) { // Replace forward declaration Debug.Assert(r.LocalName == Enum.GetName(typeof(QilNodeType), nd.NodeType), "Id '" + id + "' is not not bound to a " + r.LocalName + " forward decl"); nd = this.fwdDecls[id]; this.fwdDecls.Remove(id); if (list.Count > 0) nd[0] = list[0]; if (list.Count > 1) nd[1] = list[1]; } else { // Put reference in scope Debug.Assert(!this.scope.ContainsKey(id), "Id '" + id + "' is already in scope"); this.scope[id] = nd; } } nd.Annotation = ann; break; } case "RefTo": { // Lookup reference string id = ann.Id; Debug.Assert(id != null, r.LocalName + " must have an id attribute"); Debug.Assert(this.scope.ContainsKey(id), "Id '" + id + "' is not in scope"); this.stk.Peek().Add(this.scope[id]); return; } case "Sequence": nd = f.Sequence(list); break; case "FunctionList": nd = f.FunctionList(list); break; case "GlobalVariableList": nd = f.GlobalVariableList(list); break; case "GlobalParameterList": nd = f.GlobalParameterList(list); break; case "ActualParameterList": nd = f.ActualParameterList(list); break; case "FormalParameterList": nd = f.FormalParameterList(list); break; case "SortKeyList": nd = f.SortKeyList(list); break; case "BranchList": nd = f.BranchList(list); break; case "XsltInvokeEarlyBound": { Debug.Assert(ann.ClrNamespace != null, "XsltInvokeEarlyBound must have a clrNamespace attribute"); Debug.Assert(list.Count == 2, "XsltInvokeEarlyBound must have exactly 2 arguments"); Debug.Assert(list.XmlType != null, "XsltInvokeEarlyBound must have an xmlType attribute"); MethodInfo mi = null; QilName name = (QilName) list[0]; foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) { Type t = asm.GetType(ann.ClrNamespace); if (t != null) { mi = t.GetMethod(name.LocalName); break; } } Debug.Assert(mi != null, "Cannot find method " + ann.ClrNamespace + "." + name.ToString()); nd = f.XsltInvokeEarlyBound(name, f.LiteralObject(mi), list[1], ann.XmlType); break; } default: { // Find factory method which will be used to construct the Qil node Debug.Assert(nameToFactoryMethod.ContainsKey(r.LocalName), "Method " + r.LocalName + " could not be found on QilFactory"); facMethod = nameToFactoryMethod[r.LocalName]; Debug.Assert(facMethod.GetParameters().Length == list.Count, "NodeType " + r.LocalName + " does not allow " + list.Count + " parameters"); // Create factory method arguments facArgs = new object[list.Count]; for (int i = 0; i < facArgs.Length; i++) facArgs[i] = list[i]; // Create node and set its properties nd = (QilNode) facMethod.Invoke(f, facArgs); break; } } nd.SourceLine = list.SourceLine; // Add node to its parent's list this.stk.Peek().Add(nd); } private string ReadText() { string s = string.Empty; if (!r.IsEmptyElement) { while (r.Read()) { switch (r.NodeType) { case XmlNodeType.Text: case XmlNodeType.SignificantWhitespace: case XmlNodeType.Whitespace: s += r.Value; continue; } break; } } return s; } private ISourceLineInfo ParseLineInfo(string s) { if (s != null && s.Length > 0) { Match m = lineInfoRegex.Match(s); Debug.Assert(m.Success && m.Groups.Count == 5, "Malformed lineInfo attribute"); return new SourceLineInfo("", Int32.Parse(m.Groups[1].Value, CultureInfo.InvariantCulture), Int32.Parse(m.Groups[2].Value, CultureInfo.InvariantCulture), Int32.Parse(m.Groups[3].Value, CultureInfo.InvariantCulture), Int32.Parse(m.Groups[4].Value, CultureInfo.InvariantCulture) ); } return null; } private XmlQueryType ParseType(string s) { if (s != null && s.Length > 0) { Match m = typeInfoRegex.Match(s); Debug.Assert(m.Success && m.Groups.Count == 4, "Malformed Type info"); XmlQueryCardinality qc = new XmlQueryCardinality(m.Groups[1].Value); bool strict = bool.Parse(m.Groups[3].Value); string[] codes = m.Groups[2].Value.Split('|'); XmlQueryType[] types = new XmlQueryType[codes.Length]; for (int i = 0; i < codes.Length; i++) types[i] = XmlQueryTypeFactory.Type((XmlTypeCode)Enum.Parse(typeof(XmlTypeCode), codes[i]), strict); return XmlQueryTypeFactory.Product(XmlQueryTypeFactory.Choice(types), qc); } return null; } private QilName ParseName(string name) { string prefix, local, uri; int idx; if (name != null && name.Length > 0) { // If name contains '}' character, then namespace is non-empty idx = name.LastIndexOf('}'); if (idx != -1 && name[0] == '{') { uri = name.Substring(1, idx - 1); name = name.Substring(idx + 1); } else { uri = string.Empty; } // Parse QName ValidateNames.ParseQNameThrow(name, out prefix, out local); return f.LiteralQName(local, uri, prefix); } return null; } private class ReaderAnnotation { public string Id; public QilName Name; public XmlQueryType XmlType; public string ClrNamespace; } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- BuildManagerHost.cs
- SafeNativeMethodsMilCoreApi.cs
- FormatException.cs
- SerialErrors.cs
- FilterRepeater.cs
- MouseCaptureWithinProperty.cs
- AllMembershipCondition.cs
- XmlSchemaAnnotated.cs
- ClientProxyGenerator.cs
- AnchoredBlock.cs
- MsmqIntegrationElement.cs
- LinqDataSourceEditData.cs
- XmlSerializationReader.cs
- WeakHashtable.cs
- XmlSchemaObjectTable.cs
- FileLevelControlBuilderAttribute.cs
- CrossContextChannel.cs
- PerformanceCounterPermissionAttribute.cs
- HtmlHistory.cs
- Visual.cs
- ValidationSummary.cs
- DataObject.cs
- Graphics.cs
- NTAccount.cs
- PageStatePersister.cs
- TextDecorationUnitValidation.cs
- RotateTransform.cs
- Compiler.cs
- InputQueue.cs
- CaretElement.cs
- SecurityElement.cs
- SqlTriggerContext.cs
- DXD.cs
- uribuilder.cs
- GradientSpreadMethodValidation.cs
- DataSvcMapFile.cs
- XmlDomTextWriter.cs
- TouchesCapturedWithinProperty.cs
- XmlDataSourceNodeDescriptor.cs
- WindowsFont.cs
- ConnectorRouter.cs
- ListItemViewControl.cs
- XmlValidatingReader.cs
- SchemaReference.cs
- StructuredTypeEmitter.cs
- Triangle.cs
- Listbox.cs
- ListManagerBindingsCollection.cs
- CodeSubDirectory.cs
- ImageCollectionCodeDomSerializer.cs
- UnsafeNativeMethods.cs
- XmlSequenceWriter.cs
- TextStore.cs
- PropertyTabChangedEvent.cs
- CheckBoxFlatAdapter.cs
- _NestedMultipleAsyncResult.cs
- LinkedList.cs
- RangeBaseAutomationPeer.cs
- XmlDocumentViewSchema.cs
- Error.cs
- Graph.cs
- Image.cs
- _UriSyntax.cs
- RouteValueExpressionBuilder.cs
- SystemInformation.cs
- Stream.cs
- MessageBox.cs
- WindowsAltTab.cs
- PersistenceTypeAttribute.cs
- RichTextBoxAutomationPeer.cs
- CancelEventArgs.cs
- PropertyMap.cs
- SqlVersion.cs
- DataControlFieldCell.cs
- NetworkStream.cs
- Drawing.cs
- EdmConstants.cs
- DispatcherExceptionFilterEventArgs.cs
- StringInfo.cs
- ListItemViewControl.cs
- CaseInsensitiveComparer.cs
- Int64.cs
- AutomationAttributeInfo.cs
- ProcessModule.cs
- TextTreeTextNode.cs
- StopStoryboard.cs
- DtrList.cs
- Soap12ProtocolReflector.cs
- CodeThrowExceptionStatement.cs
- DataSet.cs
- Deflater.cs
- ListViewTableCell.cs
- IdentityHolder.cs
- FileAuthorizationModule.cs
- PeerObject.cs
- _OSSOCK.cs
- SQLDateTime.cs
- RowType.cs
- PassportIdentity.cs
- ToolboxItemFilterAttribute.cs