| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- //------------------------------------------------------------------------------
- // <copyright file="ShapeGenerator.cs" company="Microsoft">
- // Copyright (c) Microsoft Corporation. All rights reserved.
- // </copyright>
- // <owner current="true" primary="true">derekdb</owner>
- //------------------------------------------------------------------------------
- #if ENABLEDATABINDING
- using System;
- using System.Xml;
- using System.Xml.Schema;
- using System.Xml.XPath;
- using System.Collections;
- using System.Diagnostics;
- using System.ComponentModel;
- using System.Text;
- namespace System.Xml.XPath.DataBinding
- {
- internal sealed class ShapeGenerator
- {
- private Hashtable elementTypesProcessed;
- private IXmlNamespaceResolver nsResolver;
- public ShapeGenerator(IXmlNamespaceResolver nsResolver) {
- this.elementTypesProcessed = new Hashtable();
- this.nsResolver = nsResolver;
- }
- public Shape GenerateFromSchema(XmlSchemaElement xse) {
- XmlQualifiedName xseName = xse.QualifiedName;
- XmlSchemaType schemaType = xse.ElementSchemaType;
- XmlSchemaComplexType complexType = schemaType as XmlSchemaComplexType;
- if (null != complexType) {
- XmlSchemaParticle particle = null;
- Shape rootShape = null;
-
- XmlSchemaContentType contentType = complexType.ElementDecl.ContentValidator.ContentType;
- switch (contentType) {
- case XmlSchemaContentType.Mixed:
- case XmlSchemaContentType.TextOnly:
- rootShape = new Shape(GenName(xseName) + "_Text", BindingType.Text);
- rootShape.AddParticle(xse);
- break;
- case XmlSchemaContentType.Empty:
- rootShape = new Shape(null, BindingType.Sequence);
- break;
- case XmlSchemaContentType.ElementOnly:
- particle = complexType.ContentTypeParticle;
- rootShape = ProcessParticle(particle, null);
- break;
- }
-
- Debug.Assert(rootShape != null);
- if (complexType.AttributeUses.Values.Count > 0) {
- if (rootShape.BindingType != BindingType.Sequence) {
- Shape s = new Shape(null, BindingType.Sequence);
- s.AddSubShape(rootShape);
- rootShape = s;
- }
- int pos = 0;
- string[] names = rootShape.SubShapeNames();
- ICollection attributes = complexType.AttributeUses.Values;
- XmlSchemaAttribute[] xsaArray = new XmlSchemaAttribute[attributes.Count];
- attributes.CopyTo(xsaArray, 0);
- Array.Sort(xsaArray, new XmlSchemaAttributeComparer());
- foreach(XmlSchemaAttribute xsa in xsaArray) {
- string name = GenAttrName(xsa.QualifiedName, names);
- Shape attrShape = new Shape(name, BindingType.Attribute);
- attrShape.AddParticle(xsa);
- rootShape.AddAttrShapeAt(attrShape, pos++);
- }
- }
-
- if (rootShape.BindingType != BindingType.Text) {
- rootShape.Name = GenName(xseName);
- rootShape.ContainerDecl = xse;
- }
- return rootShape;
- }
- else { // simple type
- Shape s = new Shape(GenName(xseName), BindingType.Text);
- s.AddParticle(xse);
- return s;
- }
- }
- public Shape GenerateFromSchema(XmlSchemaAttribute xsa) {
- Shape s = new Shape(GenName(xsa.QualifiedName), BindingType.Attribute);
- s.AddParticle(xsa);
- return s;
- }
- Shape ProcessParticle(XmlSchemaParticle xsp, Shape parent) {
- Shape s;
- if (xsp == XmlSchemaParticle.Empty) {
- return null;
- }
- if (xsp is XmlSchemaElement) {
- s = ProcessParticleElement((XmlSchemaElement)xsp);
- }
- else if (xsp is XmlSchemaSequence) {
- s = ProcessParticleGroup((XmlSchemaSequence)xsp, BindingType.Sequence);
- }
- else if (xsp is XmlSchemaChoice) {
- s = ProcessParticleGroup((XmlSchemaChoice)xsp, BindingType.Choice);
- }
- else if (xsp is XmlSchemaAll) {
- s = ProcessParticleGroup((XmlSchemaAll)xsp, BindingType.All);
- }
- else { //XmlSchemaAny
- return null; //Ignore Any in the content model
- }
- if (xsp.MaxOccurs > 1) {
- Shape rep = new Shape(s.Name, BindingType.Repeat);
- rep.AddSubShape(s);
- s = rep;
- }
- if (parent != null)
- parent.AddSubShape(s);
- return s;
- }
- Shape ProcessParticleElement(XmlSchemaElement xse) {
- // watch out for recursive schema
- Shape s = (Shape)this.elementTypesProcessed[xse];
- if (null != s)
- return s;
- bool complex = xse.ElementSchemaType is XmlSchemaComplexType;
- s = new Shape(GenName(xse.QualifiedName), complex ? BindingType.ElementNested : BindingType.Element);
- s.AddParticle(xse);
-
- if (complex) {
- this.elementTypesProcessed.Add(xse, s);
- s.NestedShape = GenerateFromSchema(xse);
- this.elementTypesProcessed.Remove(xse);
- }
- return s;
- }
- Shape ProcessParticleGroup(XmlSchemaGroupBase xsg, BindingType bt) {
- Shape s = new Shape(null, bt);
- StringBuilder sb = new StringBuilder();
- foreach (XmlSchemaParticle xsp in xsg.Items) {
- Shape sub = ProcessParticle(xsp, s);
- if (sub != null) { //sub can be null if the child particle is xs:any
- if (sb.Length > 0)
- sb.Append('_');
- sb.Append(sub.Name);
- }
- }
- // need to also test if paretn != null for this to work
- //if (s.IsGroup && s.SubShapes.Count == 1) {
- // Shape sub = (Shape)s.SubShapes[0];
- // s.Clear();
- // return sub;
- //}
- s.Name = sb.ToString();
- return s;
- }
- string GenName(XmlQualifiedName xqn) {
- string ns = xqn.Namespace;
- string ln = xqn.Name;
- if (ns.Length != 0) {
- string prefix = (null==this.nsResolver) ? null : this.nsResolver.LookupPrefix(ns);
- if (prefix != null && prefix.Length != 0)
- return String.Concat(prefix, ":", ln);
- }
- return ln;
- }
- string GenAttrName(XmlQualifiedName xqn, string[] names) {
- string name = GenName(xqn);
- if (null != names) {
- for (int i=0; i<names.Length; i++) {
- if (name == names[i]) {
- return String.Concat("@", name);
- }
- }
- }
- return name;
- }
- public void ResetState() {
- this.elementTypesProcessed.Clear();
- }
- class XmlSchemaAttributeComparer : IComparer {
- public virtual int Compare(object a, object b) {
- XmlSchemaAttribute xsaA = (XmlSchemaAttribute)a;
- XmlSchemaAttribute xsaB = (XmlSchemaAttribute)b;
- return XmlQualifiedName.Compare(xsaA.QualifiedName, xsaB.QualifiedName);
- }
- }
- }
- }
- #endif
|