📄 xmlschemacompletiondata.cs
字号:
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
// <version>$Revision: 1340 $</version>
// </file>
using ICSharpCode.TextEditor.Gui.CompletionWindow;
using System;
using System.Collections;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Schema;
namespace ICSharpCode.XmlEditor
{
/// <summary>
/// Holds the completion (intellisense) data for an xml schema.
/// </summary>
/// <remarks>
/// The XmlSchema class throws an exception if we attempt to load
/// the xhtml1-strict.xsd schema. It does not like the fact that
/// this schema redefines the xml namespace, even though this is
/// allowed by the w3.org specification.
/// </remarks>
public class XmlSchemaCompletionData
{
string namespaceUri = String.Empty;
XmlSchema schema;
string fileName = String.Empty;
bool readOnly = false;
/// <summary>
/// Stores attributes that have been prohibited whilst the code
/// generates the attribute completion data.
/// </summary>
XmlSchemaObjectCollection prohibitedAttributes = new XmlSchemaObjectCollection();
public XmlSchemaCompletionData()
{
}
/// <summary>
/// Creates completion data from the schema passed in
/// via the reader object.
/// </summary>
public XmlSchemaCompletionData(TextReader reader)
{
ReadSchema(String.Empty, reader);
}
/// <summary>
/// Creates completion data from the schema passed in
/// via the reader object.
/// </summary>
public XmlSchemaCompletionData(XmlTextReader reader)
{
reader.XmlResolver = null;
ReadSchema(reader);
}
/// <summary>
/// Creates the completion data from the specified schema file.
/// </summary>
public XmlSchemaCompletionData(string fileName) : this(String.Empty, fileName)
{
}
/// <summary>
/// Creates the completion data from the specified schema file and uses
/// the specified baseUri to resolve any referenced schemas.
/// </summary>
public XmlSchemaCompletionData(string baseUri, string fileName)
{
StreamReader reader = new StreamReader(fileName, true);
ReadSchema(baseUri, reader);
this.fileName = fileName;
}
/// <summary>
/// Gets the schema.
/// </summary>
public XmlSchema Schema {
get {
return schema;
}
}
/// <summary>
/// Read only schemas are those that are installed with
/// SharpDevelop.
/// </summary>
public bool ReadOnly {
get {
return readOnly;
}
set {
readOnly = value;
}
}
/// <summary>
/// Gets or sets the schema's file name.
/// </summary>
public string FileName {
get {
return fileName;
}
set {
fileName = value;
}
}
/// <summary>
/// Gets the namespace URI for the schema.
/// </summary>
public string NamespaceUri {
get {
return namespaceUri;
}
}
/// <summary>
/// Converts the filename into a valid Uri.
/// </summary>
public static string GetUri(string fileName)
{
string uri = String.Empty;
if (fileName != null) {
if (fileName.Length > 0) {
uri = String.Concat("file:///", fileName.Replace('\\', '/'));
}
}
return uri;
}
/// <summary>
/// Gets the possible root elements for an xml document using this schema.
/// </summary>
public ICompletionData[] GetElementCompletionData()
{
return GetElementCompletionData(String.Empty);
}
/// <summary>
/// Gets the possible root elements for an xml document using this schema.
/// </summary>
public ICompletionData[] GetElementCompletionData(string namespacePrefix)
{
XmlCompletionDataCollection data = new XmlCompletionDataCollection();
foreach (XmlSchemaElement element in schema.Elements.Values) {
if (element.Name != null) {
AddElement(data, element.Name, namespacePrefix, element.Annotation);
} else {
// Do not add reference element.
}
}
return data.ToArray();
}
/// <summary>
/// Gets the attribute completion data for the xml element that exists
/// at the end of the specified path.
/// </summary>
public ICompletionData[] GetAttributeCompletionData(XmlElementPath path)
{
XmlCompletionDataCollection data = new XmlCompletionDataCollection();
// Locate matching element.
XmlSchemaElement element = FindElement(path);
// Get completion data.
if (element != null) {
prohibitedAttributes.Clear();
data = GetAttributeCompletionData(element);
}
return data.ToArray();
}
/// <summary>
/// Gets the child element completion data for the xml element that exists
/// at the end of the specified path.
/// </summary>
public ICompletionData[] GetChildElementCompletionData(XmlElementPath path)
{
XmlCompletionDataCollection data = new XmlCompletionDataCollection();
// Locate matching element.
XmlSchemaElement element = FindElement(path);
// Get completion data.
if (element != null) {
data = GetChildElementCompletionData(element, path.Elements.LastPrefix);
}
return data.ToArray();
}
/// <summary>
/// Gets the autocomplete data for the specified attribute value.
/// </summary>
public ICompletionData[] GetAttributeValueCompletionData(XmlElementPath path, string name)
{
XmlCompletionDataCollection data = new XmlCompletionDataCollection();
// Locate matching element.
XmlSchemaElement element = FindElement(path);
// Get completion data.
if (element != null) {
data = GetAttributeValueCompletionData(element, name);
}
return data.ToArray();
}
/// <summary>
/// Handler for schema validation errors.
/// </summary>
void SchemaValidation(object source, ValidationEventArgs e)
{
// Do nothing.
}
/// <summary>
/// Loads the schema.
/// </summary>
void ReadSchema(XmlReader reader)
{
try {
schema = XmlSchema.Read(reader, new ValidationEventHandler(SchemaValidation));
schema.Compile(new ValidationEventHandler(SchemaValidation));
namespaceUri = schema.TargetNamespace;
} finally {
reader.Close();
}
}
void ReadSchema(string baseUri, TextReader reader)
{
XmlTextReader xmlReader = new XmlTextReader(baseUri, reader);
// Setting the resolver to null allows us to
// load the xhtml1-strict.xsd without any exceptions if
// the referenced dtds exist in the same folder as the .xsd
// file. If this is not set to null the dtd files are looked
// for in the assembly's folder.
xmlReader.XmlResolver = null;
ReadSchema(xmlReader);
}
/// <summary>
/// Finds an element in the schema.
/// </summary>
/// <remarks>
/// Only looks at the elements that are defined in the
/// root of the schema so it will not find any elements
/// that are defined inside any complex types.
/// </remarks>
XmlSchemaElement FindElement(QualifiedName name)
{
XmlSchemaElement matchedElement = null;
foreach (XmlSchemaElement element in schema.Elements.Values) {
if (name.Equals(element.QualifiedName)) {
matchedElement = element;
break;
}
}
return matchedElement;
}
/// <summary>
/// Finds an element in the schema.
/// </summary>
/// <remarks>
/// Only looks at the elements that are defined in the
/// root of the schema so it will not find any elements
/// that are defined inside any complex types.
/// </remarks>
XmlSchemaElement FindElement(XmlQualifiedName name)
{
XmlSchemaElement matchedElement = null;
foreach (XmlSchemaElement element in schema.Elements.Values) {
if (name.Equals(element.QualifiedName)) {
matchedElement = element;
break;
}
}
return matchedElement;
}
XmlCompletionDataCollection GetChildElementCompletionData(XmlSchemaElement element, string prefix)
{
XmlCompletionDataCollection data = new XmlCompletionDataCollection();
XmlSchemaComplexType complexType = GetElementAsComplexType(element);
if (complexType != null) {
data = GetChildElementCompletionData(complexType, prefix);
}
return data;
}
XmlCompletionDataCollection GetChildElementCompletionData(XmlSchemaComplexType complexType, string prefix)
{
XmlCompletionDataCollection data = new XmlCompletionDataCollection();
XmlSchemaSequence sequence = complexType.Particle as XmlSchemaSequence;
XmlSchemaChoice choice = complexType.Particle as XmlSchemaChoice;
XmlSchemaGroupRef groupRef = complexType.Particle as XmlSchemaGroupRef;
XmlSchemaComplexContent complexContent = complexType.ContentModel as XmlSchemaComplexContent;
XmlSchemaAll all = complexType.Particle as XmlSchemaAll;
if (sequence != null) {
data = GetChildElementCompletionData(sequence.Items, prefix);
} else if (choice != null) {
data = GetChildElementCompletionData(choice.Items, prefix);
} else if (complexContent != null) {
data = GetChildElementCompletionData(complexContent, prefix);
} else if (groupRef != null) {
data = GetChildElementCompletionData(groupRef, prefix);
} else if (all != null) {
data = GetChildElementCompletionData(all.Items, prefix);
}
return data;
}
XmlCompletionDataCollection GetChildElementCompletionData(XmlSchemaObjectCollection items, string prefix)
{
XmlCompletionDataCollection data = new XmlCompletionDataCollection();
foreach (XmlSchemaObject schemaObject in items) {
XmlSchemaElement childElement = schemaObject as XmlSchemaElement;
XmlSchemaSequence childSequence = schemaObject as XmlSchemaSequence;
XmlSchemaChoice childChoice = schemaObject as XmlSchemaChoice;
XmlSchemaGroupRef groupRef = schemaObject as XmlSchemaGroupRef;
if (childElement != null) {
string name = childElement.Name;
if (name == null) {
name = childElement.RefName.Name;
XmlSchemaElement element = FindElement(childElement.RefName);
if (element != null) {
if (element.IsAbstract) {
AddSubstitionGroupElements(data, element.QualifiedName, prefix);
} else {
AddElement(data, name, prefix, element.Annotation);
}
} else {
AddElement(data, name, prefix, childElement.Annotation);
}
} else {
AddElement(data, name, prefix, childElement.Annotation);
}
} else if (childSequence != null) {
AddElements(data, GetChildElementCompletionData(childSequence.Items, prefix));
} else if (childChoice != null) {
AddElements(data, GetChildElementCompletionData(childChoice.Items, prefix));
} else if (groupRef != null) {
AddElements(data, GetChildElementCompletionData(groupRef, prefix));
}
}
return data;
}
XmlCompletionDataCollection GetChildElementCompletionData(XmlSchemaComplexContent complexContent, string prefix)
{
XmlCompletionDataCollection data = new XmlCompletionDataCollection();
XmlSchemaComplexContentExtension extension = complexContent.Content as XmlSchemaComplexContentExtension;
if (extension != null) {
data = GetChildElementCompletionData(extension, prefix);
} else {
XmlSchemaComplexContentRestriction restriction = complexContent.Content as XmlSchemaComplexContentRestriction;
if (restriction != null) {
data = GetChildElementCompletionData(restriction, prefix);
}
}
return data;
}
XmlCompletionDataCollection GetChildElementCompletionData(XmlSchemaComplexContentExtension extension, string prefix)
{
XmlCompletionDataCollection data = new XmlCompletionDataCollection();
XmlSchemaComplexType complexType = FindNamedType(schema, extension.BaseTypeName);
if (complexType != null) {
data = GetChildElementCompletionData(complexType, prefix);
}
// Add any elements.
if (extension.Particle != null) {
XmlSchemaSequence sequence = extension.Particle as XmlSchemaSequence;
XmlSchemaChoice choice = extension.Particle as XmlSchemaChoice;
XmlSchemaGroupRef groupRef = extension.Particle as XmlSchemaGroupRef;
if(sequence != null) {
data.AddRange(GetChildElementCompletionData(sequence.Items, prefix));
} else if (choice != null) {
data.AddRange(GetChildElementCompletionData(choice.Items, prefix));
} else if (groupRef != null) {
data.AddRange(GetChildElementCompletionData(groupRef, prefix));
}
}
return data;
}
XmlCompletionDataCollection GetChildElementCompletionData(XmlSchemaGroupRef groupRef, string prefix)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -