private string GetParticleDesc(XmlSchemaParticle particle) { var desc = particle.GetType().Name.Replace("XmlSchema", ""); if (particle is XmlSchemaElement) { desc += "(" + ((XmlSchemaElement)particle).QualifiedName + ")"; } if (particle.SourceUri == null) { if (particle.Id != null) return string.Format("{0}:id:{1}", desc, particle.Id); return string.Format("{0}:{1}:{2}", desc, particle.LineNumber, particle.LinePosition); } else { string[] segments = new Uri(particle.SourceUri).Segments; return string.Format("{0}:{1}:{2}:{3}", segments[segments.Length - 1], desc, particle.LineNumber, particle.LinePosition); } }
/// <summary> /// Index a particle. This finds the parents for all elements. /// </summary> /// <param name="parentElement">The parent element of the particle to index.</param> /// <param name="particle">The particle to index.</param> private void IndexParticle(XmlSchemaElement parentElement, XmlSchemaParticle particle) { if (particle is XmlSchemaAny) { // ignore } else if (particle is XmlSchemaChoice) { XmlSchemaChoice choice = (XmlSchemaChoice)particle; foreach (XmlSchemaParticle childParticle in choice.Items) { this.IndexParticle(parentElement, childParticle); } } else if (particle is XmlSchemaElement) { XmlSchemaElement element = (XmlSchemaElement)particle; // locally defined elements are not supported if (element.QualifiedName.Namespace.Length == 0) { throw new ApplicationException(String.Format("Locally defined element '{0}' is not supported. Please define at a global scope.", element.QualifiedName.Name)); } this.IndexElement(parentElement, element); } else if (particle is XmlSchemaGroupRef) { XmlSchemaGroupRef groupRef = (XmlSchemaGroupRef)particle; if (null != groupRef.Particle) { foreach (XmlSchemaParticle childParticle in groupRef.Particle.Items) { this.IndexParticle(parentElement, childParticle); } } } else if (particle is XmlSchemaSequence) { XmlSchemaSequence sequence = (XmlSchemaSequence)particle; foreach (XmlSchemaParticle childParticle in sequence.Items) { this.IndexParticle(parentElement, childParticle); } } else { throw new ApplicationException(String.Format("Unknown particle type: {0}.", particle.GetType().ToString())); } }
/// <summary> /// Write the particle. /// </summary> /// <param name="ownerElementInfo">Extra information about the owner element.</param> /// <param name="parentParticle">The parent of the particle being written.</param> /// <param name="particle">The particle.</param> /// <param name="writer">The html writer.</param> private void WriteParticle(XmlSchemaElementInfo ownerElementInfo, XmlSchemaParticle parentParticle, XmlSchemaParticle particle, XmlTextWriter writer) { if (particle is XmlSchemaAny) { XmlSchemaAny any = (XmlSchemaAny)particle; writer.WriteStartElement("span"); writer.WriteAttributeString("class", "extension"); writer.WriteString(String.Format("Any Element namespace='{0}' processContents='{1}'", any.Namespace, any.ProcessContents.ToString())); writer.WriteEndElement(); if (ownerElementInfo.ExtendedChildren.Count > 0) { writer.WriteStartElement("ul"); foreach (XmlQualifiedName childQualifiedName in ownerElementInfo.ExtendedChildren) { writer.WriteStartElement("li"); this.WriteElementLink(childQualifiedName, writer); writer.WriteEndElement(); } writer.WriteEndElement(); } } else if (particle is XmlSchemaChoice) { XmlSchemaChoice choice = (XmlSchemaChoice)particle; // sort element children SortedList children = new SortedList(); foreach (XmlSchemaParticle childParticle in choice.Items) { if (childParticle is XmlSchemaElement) { children.Add(((XmlSchemaElement)childParticle).QualifiedName.Name, childParticle); } else if (childParticle is XmlSchemaAny) { children.Add("ZZZ", childParticle); } else // sort non-element children by their line number { children.Add(String.Concat("Z", childParticle.LineNumber.ToString(CultureInfo.InvariantCulture)), childParticle); } } writer.WriteString(String.Format("Choice of elements (min: {0}, max: {1})", (choice.MinOccurs == Decimal.MaxValue ? "unbounded" : choice.MinOccurs.ToString(CultureInfo.InvariantCulture)), (choice.MaxOccurs == Decimal.MaxValue ? "unbounded" : choice.MaxOccurs.ToString(CultureInfo.InvariantCulture)))); writer.WriteStartElement("ul"); foreach (XmlSchemaParticle childParticle in children.Values) { writer.WriteStartElement("li"); this.WriteParticle(ownerElementInfo, particle, childParticle, writer); writer.WriteEndElement(); } writer.WriteEndElement(); } else if (particle is XmlSchemaElement) { XmlSchemaElement element = (XmlSchemaElement)particle; this.WriteElementLink(element.QualifiedName, writer); writer.WriteString(" (min: "); if (element.MinOccursString != null) { writer.WriteString(element.MinOccursString); } else if (parentParticle != null) { if (parentParticle.MinOccursString != null) { writer.WriteString(parentParticle.MinOccursString); } else { writer.WriteString(parentParticle.MinOccurs.ToString(CultureInfo.InvariantCulture)); } } writer.WriteString(", max: "); if (element.MaxOccursString != null) { writer.WriteString(element.MaxOccursString); } else if (parentParticle != null) { if (parentParticle.MaxOccursString != null) { writer.WriteString(parentParticle.MaxOccursString); } else { writer.WriteString(parentParticle.MaxOccurs.ToString(CultureInfo.InvariantCulture)); } } writer.WriteString(")"); string description = GetDescription(element); if (description != null && description.Length > 0) { writer.WriteString(": "); writer.WriteString(description); } } else if (particle is XmlSchemaSequence) { XmlSchemaSequence sequence = (XmlSchemaSequence)particle; writer.WriteString(String.Format("Sequence (min: {0}, max: {1})", (sequence.MinOccurs == Decimal.MaxValue ? "unbounded" : sequence.MinOccurs.ToString(CultureInfo.InvariantCulture)), (sequence.MaxOccurs == Decimal.MaxValue ? "unbounded" : sequence.MaxOccurs.ToString(CultureInfo.InvariantCulture)))); writer.WriteStartElement("ol"); foreach (XmlSchemaParticle childParticle in sequence.Items) { writer.WriteStartElement("li"); this.WriteParticle(ownerElementInfo, particle, childParticle, writer); writer.WriteEndElement(); } writer.WriteEndElement(); } else { throw new ApplicationException(String.Format("Unknown particle type: {0}.", particle.GetType().ToString())); } }
/// <summary> /// Write the particle. /// </summary> /// <param name="ownerElementInfo">Extra information about the owner element.</param> /// <param name="parentParticle">The parent of the particle being written.</param> /// <param name="particle">The particle.</param> /// <param name="writer">The html writer.</param> private void WriteParticle(XmlSchemaElementInfo ownerElementInfo, XmlSchemaParticle parentParticle, XmlSchemaParticle particle, XmlWriter writer) { if (particle is XmlSchemaAny) { XmlSchemaAny any = (XmlSchemaAny)particle; writer.WriteStartElement("span"); writer.WriteAttributeString("class", "extension"); writer.WriteString(String.Format("Any Element (namespace='{0}' processContents='{1}')", any.Namespace, any.ProcessContents.ToString())); string description = GetDescription(any); if (!String.IsNullOrEmpty(description)) { writer.WriteString(" "); writer.WriteRaw(description); } writer.WriteEndElement(); // TODO: Ideally, we wouldn't include children that are already listed directly. To handle // this, we'd have to keep track of all child elements we've already written (directly // or indirectly), and check the list for each of the ExtendedChildren we process. if (ownerElementInfo.ExtendedChildren.Count > 0) { writer.WriteStartElement("ul"); foreach (XmlQualifiedName childQualifiedName in ownerElementInfo.ExtendedChildren) { writer.WriteStartElement("li"); this.WriteElementLink(childQualifiedName, writer); writer.WriteEndElement(); } writer.WriteEndElement(); } } else if (particle is XmlSchemaChoice) { XmlSchemaChoice choice = (XmlSchemaChoice)particle; // sort element children SortedList children = new SortedList(); foreach (XmlSchemaParticle childParticle in choice.Items) { if (childParticle is XmlSchemaElement) { children.Add(((XmlSchemaElement)childParticle).QualifiedName.Name, childParticle); } else if (childParticle is XmlSchemaAny) { children.Add("ZZZ", childParticle); } else // sort non-element children by their line number { children.Add(String.Concat("Z", childParticle.LineNumber.ToString(CultureInfo.InvariantCulture)), childParticle); } } writer.WriteString(String.Format("Choice of elements (min: {0}, max: {1})", (choice.MinOccurs == Decimal.MaxValue ? "unbounded" : choice.MinOccurs.ToString(CultureInfo.InvariantCulture)), (choice.MaxOccurs == Decimal.MaxValue ? "unbounded" : choice.MaxOccurs.ToString(CultureInfo.InvariantCulture)))); writer.WriteStartElement("ul"); foreach (XmlSchemaParticle childParticle in children.Values) { writer.WriteStartElement("li"); this.WriteParticle(ownerElementInfo, particle, childParticle, writer); writer.WriteEndElement(); } writer.WriteEndElement(); } else if (particle is XmlSchemaElement) { XmlSchemaElement element = (XmlSchemaElement)particle; this.WriteElementLink(element.QualifiedName, writer); writer.WriteString(" (min: "); if (element.MinOccursString != null) { writer.WriteString(element.MinOccursString); } else if (parentParticle != null) { if (parentParticle.MinOccursString != null) { writer.WriteString(parentParticle.MinOccursString); } else { writer.WriteString(parentParticle.MinOccurs.ToString(CultureInfo.InvariantCulture)); } } writer.WriteString(", max: "); if (element.MaxOccursString != null) { writer.WriteString(element.MaxOccursString); } else if (parentParticle != null) { if (parentParticle.MaxOccursString != null) { writer.WriteString(parentParticle.MaxOccursString); } else { writer.WriteString(parentParticle.MaxOccurs.ToString(CultureInfo.InvariantCulture)); } } writer.WriteString(")"); string description = GetDescription(element); if (description != null && description.Length > 0) { writer.WriteString(": "); writer.WriteRaw(htmlPrefix.Replace(description.Trim().Replace("\t", String.Empty).Replace(Environment.NewLine, " "), String.Empty)); } } else if (particle is XmlSchemaSequence) { XmlSchemaSequence sequence = (XmlSchemaSequence)particle; writer.WriteString(String.Format("Sequence (min: {0}, max: {1})", (sequence.MinOccurs == Decimal.MaxValue ? "unbounded" : sequence.MinOccurs.ToString(CultureInfo.InvariantCulture)), (sequence.MaxOccurs == Decimal.MaxValue ? "unbounded" : sequence.MaxOccurs.ToString(CultureInfo.InvariantCulture)))); writer.WriteStartElement("ol"); foreach (XmlSchemaParticle childParticle in sequence.Items) { writer.WriteStartElement("li"); this.WriteParticle(ownerElementInfo, particle, childParticle, writer); writer.WriteEndElement(); } writer.WriteEndElement(); } else if (particle is XmlSchemaGroupRef) { // Document the group's children as particles of our parent. XmlSchemaGroupRef groupRef = (XmlSchemaGroupRef)particle; this.WriteParticle(ownerElementInfo, particle, groupRef.Particle, writer); } else { throw new ApplicationException(String.Format("Unknown particle type: {0}.", particle.GetType().ToString())); } }
/// <summary> /// Returns the XmlSchemaElement specified by the given qname defined in the given particle. /// </summary> /// <param name="particle"></param> /// <param name="qname"></param> /// <returns></returns> private XmlSchemaElement GetXmlSchemaElementFromParticle(XmlSchemaParticle particle, XmlQualifiedName qname) { XmlSchemaElement xe = null; var xsgb = particle as XmlSchemaGroupBase; var xsgr = particle as XmlSchemaGroupRef; if (xsgb != null) { xe = GetXmlElementFromXmlSchemaGroupBase(xsgb, qname); } else if (xsgr != null) { xe = GetXmlElementFromXmlSchemaGroupBase(xsgr.Particle, qname); } else if (particle != null) { Debug.Fail("Unable to handle case where particle type is " + particle.GetType()); } return xe; }