You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1286 lines
39 KiB
1286 lines
39 KiB
// <file> |
|
// <copyright see="prj:///doc/copyright.txt"/> |
|
// <license see="prj:///doc/license.txt"/> |
|
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/> |
|
// <version>$Revision$</version> |
|
// </file> |
|
|
|
using System; |
|
using System.Collections.Generic; |
|
using System.Collections.ObjectModel; |
|
using System.Drawing.Printing; |
|
using System.IO; |
|
using System.Text; |
|
using System.Windows.Forms; |
|
using System.Xml; |
|
using System.Xml.Schema; |
|
using System.Xml.XPath; |
|
using System.Xml.Xsl; |
|
|
|
using ICSharpCode.Core; |
|
using ICSharpCode.SharpDevelop; |
|
using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor; |
|
using ICSharpCode.SharpDevelop.Dom; |
|
using ICSharpCode.SharpDevelop.Gui; |
|
using ICSharpCode.TextEditor; |
|
using ICSharpCode.TextEditor.Actions; |
|
using ICSharpCode.TextEditor.Document; |
|
|
|
namespace ICSharpCode.XmlEditor |
|
{ |
|
/// <summary> |
|
/// Wrapper class for the XmlEditor used when displaying the xml file. |
|
/// </summary> |
|
public class XmlView : AbstractViewContent, IEditable, IClipboardHandler, IParseInformationListener, IMementoCapable, IPrintable, ITextEditorControlProvider, IPositionable, IUndoHandler |
|
{ |
|
/// <summary> |
|
/// The language handled by this view. |
|
/// </summary> |
|
public static readonly string Language = "XML"; |
|
|
|
/// <summary> |
|
/// Output window category name. |
|
/// </summary> |
|
public static readonly string CategoryName = "XML"; |
|
|
|
/// <summary> |
|
/// Edit actions addin tree path for the xml editor control. |
|
/// </summary> |
|
static readonly string editActionsPath = "/AddIns/XmlEditor/EditActions"; |
|
|
|
/// <summary> |
|
/// Right click menu addin tree path for the xml editor control. |
|
/// </summary> |
|
static readonly string contextMenuPath = "/SharpDevelop/ViewContent/XmlEditor/ContextMenu"; |
|
|
|
XmlEditorControl xmlEditor; |
|
TextEditorDisplayBindingWrapper.FileChangeWatcher watcher; |
|
static MessageViewCategory category; |
|
string stylesheetFileName; |
|
XmlTreeView xmlTreeView; |
|
|
|
/// <summary> |
|
/// Creates an XmlView that is used by SharpDevelop to provide an |
|
/// XML editor. |
|
/// </summary> |
|
public XmlView() |
|
: this(new SharpDevelopTextEditorProperties(), XmlSchemaManager.SchemaCompletionDataItems) |
|
{ |
|
watcher = new TextEditorDisplayBindingWrapper.FileChangeWatcher(this); |
|
|
|
xmlEditor.AddEditActions(GetEditActions()); |
|
xmlEditor.TextAreaContextMenuStrip = MenuService.CreateContextMenu(xmlEditor, contextMenuPath); |
|
|
|
// Add event handlers so we can update the status bar when |
|
// the cursor position changes. |
|
xmlEditor.ActiveTextAreaControl.Caret.CaretModeChanged += CaretModeChanged; |
|
xmlEditor.ActiveTextAreaControl.Caret.PositionChanged += CaretChanged; |
|
xmlEditor.ActiveTextAreaControl.Enter += CaretUpdate; |
|
|
|
// Listen for changes to the xml editor properties. |
|
XmlEditorAddInOptions.PropertyChanged += PropertyChanged; |
|
XmlSchemaManager.UserSchemaAdded += UserSchemaAdded; |
|
XmlSchemaManager.UserSchemaRemoved += UserSchemaRemoved; |
|
|
|
xmlTreeView = new XmlTreeView(this); |
|
SecondaryViewContents.Add(xmlTreeView); |
|
} |
|
|
|
/// <summary> |
|
/// Creates an XmlView that is independent of SharpDevelop. This |
|
/// constructor does rely on SharpDevelop being available and is |
|
/// only used for testing the XmlView. |
|
/// </summary> |
|
public XmlView(ITextEditorProperties textEditorProperties, XmlSchemaCompletionDataCollection schemas) |
|
{ |
|
xmlEditor = new XmlEditorControl(); |
|
xmlEditor.Dock = DockStyle.Fill; |
|
|
|
xmlEditor.TextEditorProperties = textEditorProperties; |
|
xmlEditor.SchemaCompletionDataItems = schemas; |
|
xmlEditor.Document.DocumentChanged += DocumentChanged; |
|
} |
|
|
|
/// <summary> |
|
/// Gets the active XmlView. |
|
/// </summary> |
|
/// <returns><see langword="null"/> if the active view is not an XmlView.</returns> |
|
public static XmlView ActiveXmlView { |
|
get { |
|
IWorkbench workbench = WorkbenchSingleton.Workbench; |
|
if (workbench != null) { |
|
IWorkbenchWindow window = workbench.ActiveWorkbenchWindow; |
|
if (window != null) { |
|
return window.ActiveViewContent as XmlView; |
|
} |
|
} |
|
return null; |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Gets whether the active view is an XmlView. |
|
/// </summary> |
|
public static bool IsXmlViewActive { |
|
get { |
|
return ActiveXmlView != null; |
|
} |
|
} |
|
|
|
public override string TabPageText { |
|
get { |
|
return "XML"; |
|
} |
|
} |
|
|
|
public XmlEditorControl XmlEditor { |
|
get { |
|
return xmlEditor; |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Loads the string content into the view. |
|
/// </summary> |
|
public void LoadContent(string content) |
|
{ |
|
xmlEditor.Document.TextContent = StringParser.Parse(content); |
|
xmlEditor.Document.HighlightingStrategy = HighlightingStrategyFactory.CreateHighlightingStrategy(XmlView.Language); |
|
UpdateFolding(); |
|
} |
|
|
|
/// <summary> |
|
/// Can create content for the 'XML' language. |
|
/// </summary> |
|
public static bool IsLanguageHandled(string language) |
|
{ |
|
return language == XmlView.Language; |
|
} |
|
|
|
/// <summary> |
|
/// Returns whether the view can handle the specified file. |
|
/// </summary> |
|
public static bool IsFileNameHandled(string fileName) |
|
{ |
|
return IsXmlFileExtension(Path.GetExtension(fileName)); |
|
} |
|
|
|
/// <summary> |
|
/// Gets the known xml file extensions. |
|
/// </summary> |
|
public static string[] GetXmlFileExtensions() |
|
{ |
|
foreach (ParserDescriptor parser in (ParserDescriptor[])AddInTree.BuildItems("/Workspace/Parser", null, false).ToArray(typeof(ParserDescriptor))) { |
|
if (parser.Codon.Id == "XmlFoldingParser") { |
|
return parser.Supportedextensions; |
|
} |
|
} |
|
|
|
// Did not find the XmlFoldingParser so default to those files defined by the |
|
// HighlightingManager. |
|
IHighlightingStrategy strategy = HighlightingManager.Manager.FindHighlighter(XmlView.Language); |
|
if (strategy != null) { |
|
return strategy.Extensions; |
|
} |
|
|
|
return new string[0]; |
|
} |
|
|
|
/// <summary> |
|
/// Finds the xml nodes that match the specified xpath. |
|
/// </summary> |
|
/// <returns>An array of XPathNodeMatch items. These include line number |
|
/// and line position information aswell as the node found.</returns> |
|
public static XPathNodeMatch[] SelectNodes(string xml, string xpath, ReadOnlyCollection<XmlNamespace> namespaces) |
|
{ |
|
XmlTextReader xmlReader = new XmlTextReader(new StringReader(xml)); |
|
xmlReader.XmlResolver = null; |
|
XPathDocument doc = new XPathDocument(xmlReader); |
|
XPathNavigator navigator = doc.CreateNavigator(); |
|
|
|
// Add namespaces. |
|
XmlNamespaceManager namespaceManager = new XmlNamespaceManager(navigator.NameTable); |
|
foreach (XmlNamespace xmlNamespace in namespaces) { |
|
namespaceManager.AddNamespace(xmlNamespace.Prefix, xmlNamespace.Uri); |
|
} |
|
|
|
// Run the xpath query. |
|
XPathNodeIterator iterator = navigator.Select(xpath, namespaceManager); |
|
|
|
List<XPathNodeMatch> nodes = new List<XPathNodeMatch>(); |
|
while (iterator.MoveNext()) { |
|
nodes.Add(new XPathNodeMatch(iterator.Current)); |
|
} |
|
return nodes.ToArray(); |
|
} |
|
|
|
/// <summary> |
|
/// Finds the xml nodes that match the specified xpath. |
|
/// </summary> |
|
/// <returns>An array of XPathNodeMatch items. These include line number |
|
/// and line position information aswell as the node found.</returns> |
|
public static XPathNodeMatch[] SelectNodes(string xml, string xpath) |
|
{ |
|
List<XmlNamespace> list = new List<XmlNamespace>(); |
|
return SelectNodes(xml, xpath, new ReadOnlyCollection<XmlNamespace>(list)); |
|
} |
|
|
|
/// <summary> |
|
/// Finds the xml nodes in the current document that match the specified xpath. |
|
/// </summary> |
|
/// <returns>An array of XPathNodeMatch items. These include line number |
|
/// and line position information aswell as the node found.</returns> |
|
public XPathNodeMatch[] SelectNodes(string xpath, ReadOnlyCollection<XmlNamespace> namespaces) |
|
{ |
|
return SelectNodes(Text, xpath, namespaces); |
|
} |
|
|
|
/// <summary> |
|
/// Gets the XmlSchemaObject that defines the currently selected xml element or |
|
/// attribute. |
|
/// </summary> |
|
/// <param name="text">The complete xml text.</param> |
|
/// <param name="index">The current cursor index.</param> |
|
/// <param name="provider">The completion data provider</param> |
|
public static XmlSchemaObject GetSchemaObjectSelected(string xml, int index, XmlCompletionDataProvider provider) |
|
{ |
|
return GetSchemaObjectSelected(xml, index, provider, null); |
|
} |
|
|
|
/// <summary> |
|
/// Gets the XmlSchemaObject that defines the currently selected xml element or |
|
/// attribute. |
|
/// </summary> |
|
/// <param name="text">The complete xml text.</param> |
|
/// <param name="index">The current cursor index.</param> |
|
/// <param name="provider">The completion data provider</param> |
|
/// <param name="currentSchemaCompletionData">This is the schema completion data for the |
|
/// schema currently being displayed. This can be null if the document is |
|
/// not a schema.</param> |
|
public static XmlSchemaObject GetSchemaObjectSelected(string xml, int index, XmlCompletionDataProvider provider, XmlSchemaCompletionData currentSchemaCompletionData) |
|
{ |
|
// Find element under cursor. |
|
XmlElementPath path = XmlParser.GetActiveElementStartPathAtIndex(xml, index); |
|
string attributeName = XmlParser.GetAttributeNameAtIndex(xml, index); |
|
|
|
// Find schema definition object. |
|
XmlSchemaCompletionData schemaCompletionData = provider.FindSchema(path); |
|
XmlSchemaObject schemaObject = null; |
|
if (schemaCompletionData != null) { |
|
XmlSchemaElement element = schemaCompletionData.FindElement(path); |
|
schemaObject = element; |
|
if (element != null) { |
|
if (attributeName.Length > 0) { |
|
XmlSchemaAttribute attribute = schemaCompletionData.FindAttribute(element, attributeName); |
|
if (attribute != null) { |
|
if (currentSchemaCompletionData != null) { |
|
schemaObject = GetSchemaObjectReferenced(xml, index, provider, currentSchemaCompletionData, element, attribute); |
|
} else { |
|
schemaObject = attribute; |
|
} |
|
} |
|
} |
|
return schemaObject; |
|
} |
|
} |
|
return null; |
|
} |
|
|
|
/// <summary> |
|
/// Validates the xml against known schemas. |
|
/// </summary> |
|
public void ValidateXml() |
|
{ |
|
TaskService.ClearExceptCommentTasks(); |
|
Category.ClearText(); |
|
ShowOutputWindow(); |
|
|
|
OutputWindowWriteLine(StringParser.Parse("${res:MainWindow.XmlValidationMessages.ValidationStarted}")); |
|
|
|
if (IsSchema) { |
|
if (!ValidateSchema()) { |
|
return; |
|
} |
|
} else { |
|
if (!ValidateAgainstSchema()) { |
|
return; |
|
} |
|
} |
|
|
|
OutputWindowWriteLine(String.Empty); |
|
OutputWindowWriteLine(StringParser.Parse("${res:MainWindow.XmlValidationMessages.ValidationSuccess}")); |
|
} |
|
|
|
/// <summary> |
|
/// Gets the name of a new view. |
|
/// </summary> |
|
public override string UntitledName { |
|
get { |
|
return base.UntitledName; |
|
} |
|
set { |
|
base.UntitledName = value; |
|
xmlEditor.FileName = value; |
|
SetDefaultSchema(Path.GetExtension(xmlEditor.FileName)); |
|
} |
|
} |
|
|
|
public override void Dispose() |
|
{ |
|
base.Dispose(); |
|
if (watcher != null) { |
|
watcher.Dispose(); |
|
XmlEditorAddInOptions.PropertyChanged -= PropertyChanged; |
|
XmlSchemaManager.UserSchemaAdded -= new EventHandler(UserSchemaAdded); |
|
XmlSchemaManager.UserSchemaRemoved -= new EventHandler(UserSchemaRemoved); |
|
} |
|
xmlEditor.Dispose(); |
|
} |
|
|
|
/// <summary> |
|
/// Sets the filename associated with the view. |
|
/// </summary> |
|
public override string FileName { |
|
set { |
|
string extension = Path.GetExtension(value); |
|
if (Path.GetExtension(FileName) != extension) { |
|
if (xmlEditor.Document.HighlightingStrategy != null) { |
|
if (XmlView.IsXmlFileExtension(extension)) { |
|
xmlEditor.Document.HighlightingStrategy = HighlightingStrategyFactory.CreateHighlightingStrategy(XmlView.Language); |
|
} else { |
|
xmlEditor.Document.HighlightingStrategy = HighlightingStrategyFactory.CreateHighlightingStrategyForFile(value); |
|
} |
|
xmlEditor.Refresh(); |
|
} |
|
} |
|
base.FileName = value; |
|
base.TitleName = Path.GetFileName(value); |
|
|
|
SetDefaultSchema(extension); |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Gets or sets the stylesheet associated with this xml file. |
|
/// </summary> |
|
public string StylesheetFileName { |
|
get { |
|
return stylesheetFileName; |
|
} |
|
set { |
|
stylesheetFileName = value; |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Applys the stylesheet to the xml and displays the resulting output. |
|
/// </summary> |
|
public void RunXslTransform(string xsl) |
|
{ |
|
try { |
|
WorkbenchSingleton.Workbench.GetPad(typeof(CompilerMessageView)).BringPadToFront(); |
|
|
|
TaskService.ClearExceptCommentTasks(); |
|
|
|
if (IsWellFormed) { |
|
if (IsValidXsl(xsl)) { |
|
string transformedXml = Transform(Text, xsl); |
|
ShowTransformOutput(transformedXml); |
|
} |
|
} |
|
|
|
ShowErrorList(); |
|
|
|
} catch (Exception ex) { |
|
MessageService.ShowError(ex); |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Pretty prints the xml. |
|
/// </summary> |
|
public void FormatXml() |
|
{ |
|
TaskService.ClearExceptCommentTasks(); |
|
|
|
if (IsWellFormed) { |
|
ReplaceAll(Text); |
|
} else { |
|
ShowErrorList(); |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Creates a schema based on the xml content. |
|
/// </summary> |
|
/// <returns>A set of generated schemas or null if the xml content is not |
|
/// well formed.</returns> |
|
public string[] InferSchema() |
|
{ |
|
TaskService.ClearExceptCommentTasks(); |
|
if (IsWellFormed) { |
|
try { |
|
using (XmlTextReader reader = new XmlTextReader(new StringReader(Text))) { |
|
XmlSchemaInference schemaInference = new XmlSchemaInference(); |
|
XmlSchemaSet schemaSet = schemaInference.InferSchema(reader); |
|
return GetSchemas(schemaSet); |
|
} |
|
} catch (XmlSchemaInferenceException ex) { |
|
AddTask(xmlEditor.FileName, ex.Message, ex.LinePosition, ex.LineNumber, TaskType.Error); |
|
} |
|
} |
|
ShowErrorList(); |
|
return null; |
|
} |
|
|
|
/// <summary> |
|
/// Finds the definition of the xml element or attribute under the cursor |
|
/// in the corresponding schema and then displays that schema and the definition |
|
/// found. |
|
/// </summary> |
|
public void GoToSchemaDefinition() |
|
{ |
|
// Find schema object for selected xml element or attribute. |
|
XmlCompletionDataProvider provider = new XmlCompletionDataProvider(xmlEditor.SchemaCompletionDataItems, xmlEditor.DefaultSchemaCompletionData, xmlEditor.DefaultNamespacePrefix); |
|
XmlSchemaCompletionData currentSchemaCompletionData = provider.FindSchemaFromFileName(FileName); |
|
XmlSchemaObject schemaObject = GetSchemaObjectSelected(Text, xmlEditor.ActiveTextAreaControl.Caret.Offset, provider, currentSchemaCompletionData); |
|
|
|
// Open schema. |
|
if (schemaObject != null && schemaObject.SourceUri != null && schemaObject.SourceUri.Length > 0) { |
|
string fileName = schemaObject.SourceUri.Replace("file:///", String.Empty); |
|
FileService.JumpToFilePosition(fileName, schemaObject.LineNumber - 1, schemaObject.LinePosition - 1); |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Checks that the xml is well formed. Any errors are displayed in the |
|
/// errors list. |
|
/// </summary> |
|
public void CheckIsWellFormed() |
|
{ |
|
TaskService.ClearExceptCommentTasks(); |
|
if (!IsWellFormed) { |
|
ShowErrorList(); |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Replaces the entire text of the xml view with the xml in the |
|
/// specified. The xml will be formatted. |
|
/// </summary> |
|
public void ReplaceAll(string xml) |
|
{ |
|
string formattedXml = SimpleFormat(IndentedFormat(xml)); |
|
xmlEditor.Document.Replace(0, xmlEditor.Document.TextLength, formattedXml); |
|
UpdateFolding(); |
|
} |
|
|
|
#region IEditable interface |
|
|
|
public IClipboardHandler ClipboardHandler { |
|
get { |
|
return this; |
|
} |
|
} |
|
|
|
public bool EnableUndo { |
|
get { |
|
return xmlEditor.EnableUndo; |
|
} |
|
} |
|
|
|
public bool EnableRedo { |
|
get { |
|
return xmlEditor.EnableRedo; |
|
} |
|
} |
|
|
|
// ParserUpdateThread uses the text property via IEditable, I had an exception |
|
// because multiple threads were accessing the GapBufferStrategy at the same time. |
|
internal string GetText() |
|
{ |
|
return xmlEditor.Document.TextContent; |
|
} |
|
|
|
internal void SetText(string value) |
|
{ |
|
xmlEditor.Document.TextContent = value; |
|
} |
|
|
|
public string Text { |
|
get { |
|
if (WorkbenchSingleton.InvokeRequired) { |
|
return WorkbenchSingleton.SafeThreadFunction<string>(GetText); |
|
} else { |
|
return GetText(); |
|
} |
|
} |
|
set { |
|
if (WorkbenchSingleton.InvokeRequired) { |
|
WorkbenchSingleton.SafeThreadCall(SetText, value); |
|
} else { |
|
SetText(value); |
|
} |
|
} |
|
} |
|
|
|
public void Redo() |
|
{ |
|
xmlEditor.Redo(); |
|
} |
|
|
|
public void Undo() |
|
{ |
|
xmlEditor.Undo(); |
|
} |
|
|
|
#endregion |
|
|
|
#region AbstractViewContent implementation |
|
|
|
public override Control Control { |
|
get { |
|
return xmlEditor; |
|
} |
|
} |
|
|
|
public override void Load(string fileName) |
|
{ |
|
xmlEditor.IsReadOnly = IsFileReadOnly(fileName); |
|
xmlEditor.LoadFile(fileName, false, true); |
|
FileName = fileName; |
|
TitleName = Path.GetFileName(fileName); |
|
IsDirty = false; |
|
|
|
// Add bookmarks. |
|
foreach (ICSharpCode.SharpDevelop.Bookmarks.SDBookmark bookmark in ICSharpCode.SharpDevelop.Bookmarks.BookmarkManager.GetBookmarks(fileName)) { |
|
bookmark.Document = xmlEditor.Document; |
|
xmlEditor.Document.BookmarkManager.Marks.Add(bookmark); |
|
} |
|
|
|
UpdateFolding(); |
|
watcher.SetWatcher(fileName); |
|
} |
|
|
|
public override void Save(string fileName) |
|
{ |
|
OnSaving(EventArgs.Empty); |
|
watcher.Disable(); |
|
|
|
xmlEditor.SaveFile(fileName); |
|
FileName = fileName; |
|
TitleName = Path.GetFileName(fileName); |
|
IsDirty = false; |
|
|
|
watcher.SetWatcher(fileName); |
|
OnSaved(new SaveEventArgs(true)); |
|
} |
|
|
|
public override INavigationPoint BuildNavPoint() |
|
{ |
|
int line = Line; |
|
LineSegment lineSegment = xmlEditor.Document.GetLineSegment(line); |
|
string text = xmlEditor.Document.GetText(lineSegment); |
|
return new TextNavigationPoint(FileName, line, Column, text); |
|
} |
|
|
|
#endregion |
|
|
|
#region IClipboardHandler interface |
|
|
|
public bool EnableCut { |
|
get { |
|
return xmlEditor.ActiveTextAreaControl.TextArea.ClipboardHandler.EnableCut; |
|
} |
|
} |
|
|
|
public bool EnableCopy { |
|
get { |
|
return xmlEditor.ActiveTextAreaControl.TextArea.ClipboardHandler.EnableCopy; |
|
} |
|
} |
|
|
|
public bool EnablePaste { |
|
get { |
|
return xmlEditor.ActiveTextAreaControl.TextArea.ClipboardHandler.EnablePaste; |
|
} |
|
} |
|
|
|
public bool EnableDelete { |
|
get { |
|
return xmlEditor.ActiveTextAreaControl.TextArea.ClipboardHandler.EnableDelete; |
|
} |
|
} |
|
|
|
public bool EnableSelectAll { |
|
get { |
|
return xmlEditor.ActiveTextAreaControl.TextArea.ClipboardHandler.EnableSelectAll; |
|
} |
|
} |
|
|
|
public void SelectAll() |
|
{ |
|
xmlEditor.ActiveTextAreaControl.TextArea.ClipboardHandler.SelectAll(null, EventArgs.Empty); |
|
} |
|
|
|
public void Delete() |
|
{ |
|
xmlEditor.ActiveTextAreaControl.TextArea.ClipboardHandler.Delete(null, EventArgs.Empty); |
|
} |
|
|
|
public void Paste() |
|
{ |
|
xmlEditor.ActiveTextAreaControl.TextArea.ClipboardHandler.Paste(null, EventArgs.Empty); |
|
} |
|
|
|
public void Copy() |
|
{ |
|
xmlEditor.ActiveTextAreaControl.TextArea.ClipboardHandler.Copy(null, EventArgs.Empty); |
|
} |
|
|
|
public void Cut() |
|
{ |
|
xmlEditor.ActiveTextAreaControl.TextArea.ClipboardHandler.Cut(null, EventArgs.Empty); |
|
} |
|
|
|
#endregion |
|
|
|
#region IParseInformationListener interface |
|
|
|
public void ParseInformationUpdated(ParseInformation parseInfo) |
|
{ |
|
WorkbenchSingleton.SafeThreadAsyncCall(UpdateFolding); |
|
} |
|
|
|
#endregion |
|
|
|
#region IMementoCapable interface |
|
|
|
public void SetMemento(Properties properties) |
|
{ |
|
xmlEditor.ActiveTextAreaControl.Caret.Position = xmlEditor.Document.OffsetToPosition(Math.Min(xmlEditor.Document.TextLength, Math.Max(0, properties.Get("CaretOffset", xmlEditor.ActiveTextAreaControl.Caret.Offset)))); |
|
|
|
if (xmlEditor.Document.HighlightingStrategy.Name != properties.Get("HighlightingLanguage", xmlEditor.Document.HighlightingStrategy.Name)) { |
|
IHighlightingStrategy highlightingStrategy = HighlightingStrategyFactory.CreateHighlightingStrategy(properties.Get("HighlightingLanguage", xmlEditor.Document.HighlightingStrategy.Name)); |
|
if (highlightingStrategy != null) { |
|
xmlEditor.Document.HighlightingStrategy = highlightingStrategy; |
|
} |
|
} |
|
xmlEditor.ActiveTextAreaControl.TextArea.TextView.FirstVisibleLine = properties.Get("VisibleLine", 0); |
|
xmlEditor.Document.FoldingManager.DeserializeFromString(properties.Get("Foldings", String.Empty)); |
|
} |
|
|
|
public Properties CreateMemento() |
|
{ |
|
Properties properties = new Properties(); |
|
properties.Set("CaretOffset", xmlEditor.ActiveTextAreaControl.Caret.Offset); |
|
properties.Set("VisibleLine", xmlEditor.ActiveTextAreaControl.TextArea.TextView.FirstVisibleLine); |
|
properties.Set("HighlightingLanguage", xmlEditor.Document.HighlightingStrategy.Name); |
|
properties.Set("Foldings", xmlEditor.Document.FoldingManager.SerializeToString()); |
|
return properties; |
|
} |
|
|
|
#endregion |
|
|
|
#region IPrintable interface |
|
|
|
public PrintDocument PrintDocument{ |
|
get { |
|
return xmlEditor.PrintDocument; |
|
} |
|
} |
|
|
|
#endregion |
|
|
|
#region ITextEditorControlProvider interface |
|
|
|
public TextEditorControl TextEditorControl { |
|
get { |
|
return xmlEditor; |
|
} |
|
} |
|
#endregion |
|
|
|
#region IPositionable interface |
|
|
|
/// <summary> |
|
/// Moves the cursor to the specified line and column. |
|
/// </summary> |
|
public void JumpTo(int line, int column) |
|
{ |
|
xmlEditor.ActiveTextAreaControl.JumpTo(line, column); |
|
} |
|
|
|
public int Line { |
|
get { |
|
return xmlEditor.ActiveTextAreaControl.Caret.Line; |
|
} |
|
} |
|
|
|
public int Column { |
|
get { |
|
return xmlEditor.ActiveTextAreaControl.Caret.Column; |
|
} |
|
} |
|
|
|
#endregion |
|
|
|
protected override void OnFileNameChanged(EventArgs e) |
|
{ |
|
base.OnFileNameChanged(e); |
|
xmlEditor.FileName = base.FileName; |
|
ICSharpCode.SharpDevelop.Bookmarks.SDBookmarkFactory factory = (ICSharpCode.SharpDevelop.Bookmarks.SDBookmarkFactory)xmlEditor.Document.BookmarkManager.Factory; |
|
factory.ChangeFilename(base.FileName); |
|
} |
|
|
|
static bool IsFileReadOnly(string fileName) |
|
{ |
|
return (File.GetAttributes(fileName) & FileAttributes.ReadOnly) == FileAttributes.ReadOnly; |
|
} |
|
|
|
/// <summary> |
|
/// Checks that the file extension refers to an xml file as |
|
/// specified in the SyntaxModes.xml file. |
|
/// </summary> |
|
static bool IsXmlFileExtension(string extension) |
|
{ |
|
foreach (string currentExtension in GetXmlFileExtensions()) { |
|
if (String.Compare(extension, currentExtension, true) == 0) { |
|
return true; |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
/// <summary> |
|
/// Forces the editor to update its folds. |
|
/// </summary> |
|
void UpdateFolding() |
|
{ |
|
xmlEditor.Document.FoldingManager.UpdateFoldings(String.Empty, null); |
|
RefreshMargin(); |
|
} |
|
|
|
/// <summary> |
|
/// Repaints the folds in the margin. |
|
/// </summary> |
|
void RefreshMargin() |
|
{ |
|
WorkbenchSingleton.SafeThreadAsyncCall(xmlEditor.ActiveTextAreaControl.TextArea.Refresh, |
|
xmlEditor.ActiveTextAreaControl.TextArea.FoldMargin); |
|
} |
|
|
|
/// <summary> |
|
/// Sets the dirty flag since the document has changed. |
|
/// </summary> |
|
void DocumentChanged(object sender, DocumentEventArgs e) |
|
{ |
|
IsDirty = true; |
|
} |
|
|
|
/// <summary> |
|
/// Updates the line, col, overwrite/insert mode in the status bar. |
|
/// </summary> |
|
void CaretUpdate(object sender, EventArgs e) |
|
{ |
|
CaretChanged(sender, e); |
|
CaretModeChanged(sender, e); |
|
} |
|
|
|
/// <summary> |
|
/// Updates the line, col information in the status bar. |
|
/// </summary> |
|
void CaretChanged(object sender, EventArgs e) |
|
{ |
|
TextAreaControl activeTextAreaControl = xmlEditor.ActiveTextAreaControl; |
|
int line = activeTextAreaControl.Caret.Line; |
|
int col = activeTextAreaControl.Caret.Column; |
|
StatusBarService.SetCaretPosition(activeTextAreaControl.TextArea.TextView.GetVisualColumn(line, col), line, col); |
|
} |
|
|
|
/// <summary> |
|
/// Updates the insert/overwrite mode text in the status bar. |
|
/// </summary> |
|
void CaretModeChanged(object sender, EventArgs e) |
|
{ |
|
StatusBarService.SetInsertMode(xmlEditor.ActiveTextAreaControl.Caret.CaretMode == CaretMode.InsertMode); |
|
} |
|
|
|
/// <summary> |
|
/// Gets the xml validation output window. |
|
/// </summary> |
|
MessageViewCategory Category { |
|
get { |
|
if (category == null) { |
|
category = new MessageViewCategory(CategoryName); |
|
CompilerMessageView cmv = (CompilerMessageView)WorkbenchSingleton.Workbench.GetPad(typeof(CompilerMessageView)).PadContent; |
|
cmv.AddCategory(category); |
|
} |
|
|
|
return category; |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Brings output window pad to the front. |
|
/// </summary> |
|
void ShowOutputWindow() |
|
{ |
|
WorkbenchSingleton.Workbench.GetPad(typeof(CompilerMessageView)).BringPadToFront(); |
|
} |
|
|
|
/// <summary> |
|
/// Writes a line of text to the output window. |
|
/// </summary> |
|
/// <param name="message">The message to send to the output |
|
/// window.</param> |
|
void OutputWindowWriteLine(string message) |
|
{ |
|
Category.AppendText(String.Concat(message, Environment.NewLine)); |
|
} |
|
|
|
void ShowErrorList() |
|
{ |
|
if (ErrorListPad.ShowAfterBuild && TaskService.SomethingWentWrong) { |
|
WorkbenchSingleton.Workbench.GetPad(typeof(ErrorListPad)).BringPadToFront(); |
|
} |
|
} |
|
|
|
void AddTask(string fileName, string message, int column, int line, TaskType taskType) |
|
{ |
|
TaskService.Add(new Task(fileName, message, column, line, taskType)); |
|
} |
|
|
|
/// <summary> |
|
/// Displays the validation error. |
|
/// </summary> |
|
void DisplayValidationError(string fileName, string message, int column, int line) |
|
{ |
|
OutputWindowWriteLine(message); |
|
AddTask(fileName, message, column, line, TaskType.Error); |
|
} |
|
|
|
void ShowValidationFailedMessage() |
|
{ |
|
OutputWindowWriteLine(String.Empty); |
|
OutputWindowWriteLine(StringParser.Parse("${res:MainWindow.XmlValidationMessages.ValidationFailed}")); |
|
} |
|
|
|
/// <summary> |
|
/// Updates the default schema associated with the xml editor. |
|
/// </summary> |
|
void PropertyChanged(object sender, PropertyChangedEventArgs e) |
|
{ |
|
string extension = Path.GetExtension(xmlEditor.FileName).ToLowerInvariant(); |
|
if (e.Key == String.Concat("ext", extension)) { |
|
SetDefaultSchema(extension); |
|
} else if (e.Key == XmlEditorAddInOptions.ShowAttributesWhenFoldedPropertyName) { |
|
UpdateFolding(); |
|
xmlEditor.Refresh(); |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Sets the default schema and namespace prefix that the xml editor will use. |
|
/// </summary> |
|
void SetDefaultSchema(string extension) |
|
{ |
|
xmlEditor.DefaultSchemaCompletionData = XmlSchemaManager.GetSchemaCompletionData(extension); |
|
xmlEditor.DefaultNamespacePrefix = XmlSchemaManager.GetNamespacePrefix(extension); |
|
} |
|
|
|
/// <summary> |
|
/// Updates the default schema association since the schema |
|
/// may have been added. |
|
/// </summary> |
|
void UserSchemaAdded(object source, EventArgs e) |
|
{ |
|
SetDefaultSchema(Path.GetExtension(xmlEditor.FileName).ToLowerInvariant()); |
|
} |
|
|
|
/// <summary> |
|
/// Updates the default schema association since the schema |
|
/// may have been removed. |
|
/// </summary> |
|
void UserSchemaRemoved(object source, EventArgs e) |
|
{ |
|
SetDefaultSchema(Path.GetExtension(xmlEditor.FileName).ToLowerInvariant()); |
|
} |
|
|
|
/// <summary> |
|
/// Displays the transformed output. |
|
/// </summary> |
|
void ShowTransformOutput(string xml) |
|
{ |
|
// Pretty print the xml. |
|
xml = SimpleFormat(IndentedFormat(xml)); |
|
|
|
// Display the output xml. |
|
XslOutputView view = XslOutputView.Instance; |
|
if (view == null) { |
|
view = new XslOutputView(); |
|
view.LoadContent(xml); |
|
WorkbenchSingleton.Workbench.ShowView(view); |
|
} else { |
|
// Transform output window already opened. |
|
view.LoadContent(xml); |
|
view.WorkbenchWindow.SelectWindow(); |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Returns a formatted xml string using a simple formatting algorithm. |
|
/// </summary> |
|
static string SimpleFormat(string xml) |
|
{ |
|
return xml.Replace("><", ">\r\n<"); |
|
} |
|
|
|
/// <summary> |
|
/// Runs an XSL transform on the input xml. |
|
/// </summary> |
|
/// <param name="input">The input xml to transform.</param> |
|
/// <param name="transform">The transform xml.</param> |
|
/// <returns>The output of the transform.</returns> |
|
static string Transform(string input, string transform) |
|
{ |
|
StringReader inputString = new StringReader(input); |
|
XmlTextReader sourceDocument = new XmlTextReader(inputString); |
|
|
|
StringReader transformString = new StringReader(transform); |
|
XPathDocument transformDocument = new XPathDocument(transformString); |
|
|
|
XslCompiledTransform xslTransform = new XslCompiledTransform(); |
|
xslTransform.Load(transformDocument, XsltSettings.Default, new XmlUrlResolver()); |
|
|
|
MemoryStream outputStream = new MemoryStream(); |
|
XmlTextWriter writer = new XmlTextWriter(outputStream, Encoding.UTF8); |
|
|
|
xslTransform.Transform(sourceDocument, null, writer); |
|
|
|
int preambleLength = Encoding.UTF8.GetPreamble().Length; |
|
byte[] outputBytes = outputStream.ToArray(); |
|
return UTF8Encoding.UTF8.GetString(outputBytes, preambleLength, outputBytes.Length - preambleLength); |
|
} |
|
|
|
/// <summary> |
|
/// Returns a pretty print version of the given xml. |
|
/// </summary> |
|
/// <param name="xml">Xml string to pretty print.</param> |
|
/// <returns>A pretty print version of the specified xml. If the |
|
/// string is not well formed xml the original string is returned. |
|
/// </returns> |
|
string IndentedFormat(string xml) |
|
{ |
|
string indentedText = String.Empty; |
|
|
|
try { |
|
XmlTextReader reader = new XmlTextReader(new StringReader(xml)); |
|
reader.WhitespaceHandling = WhitespaceHandling.None; |
|
|
|
StringWriter indentedXmlWriter = new StringWriter(); |
|
XmlTextWriter writer = CreateXmlTextWriter(indentedXmlWriter); |
|
writer.WriteNode(reader, false); |
|
writer.Flush(); |
|
|
|
indentedText = indentedXmlWriter.ToString(); |
|
} catch(Exception) { |
|
indentedText = xml; |
|
} |
|
|
|
return indentedText; |
|
} |
|
|
|
XmlTextWriter CreateXmlTextWriter(TextWriter textWriter) |
|
{ |
|
XmlTextWriter writer = new XmlTextWriter(textWriter); |
|
if (xmlEditor.TextEditorProperties.ConvertTabsToSpaces) { |
|
writer.Indentation = xmlEditor.TextEditorProperties.TabIndent; |
|
writer.IndentChar = ' '; |
|
} else { |
|
writer.Indentation = 1; |
|
writer.IndentChar = '\t'; |
|
} |
|
writer.Formatting = Formatting.Indented; |
|
return writer; |
|
} |
|
|
|
/// <summary> |
|
/// Checks that the xml in this view is well-formed. |
|
/// </summary> |
|
bool IsWellFormed { |
|
get { |
|
try { |
|
XmlDocument Document = new XmlDocument(); |
|
Document.LoadXml(Text); |
|
return true; |
|
} catch(XmlException ex) { |
|
AddTask(xmlEditor.FileName, ex.Message, ex.LinePosition - 1, ex.LineNumber - 1, TaskType.Error); |
|
} |
|
return false; |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Validates the given xsl string,. |
|
/// </summary> |
|
bool IsValidXsl(string xml) |
|
{ |
|
try { |
|
WorkbenchSingleton.Workbench.GetPad(typeof(CompilerMessageView)).BringPadToFront(); |
|
|
|
StringReader reader = new StringReader(xml); |
|
XPathDocument doc = new XPathDocument(reader); |
|
|
|
XslCompiledTransform xslTransform = new XslCompiledTransform(); |
|
xslTransform.Load(doc, XsltSettings.Default, new XmlUrlResolver()); |
|
|
|
return true; |
|
} catch(XsltCompileException ex) { |
|
string message = String.Empty; |
|
|
|
if(ex.InnerException != null) { |
|
message = ex.InnerException.Message; |
|
} else { |
|
message = ex.ToString(); |
|
} |
|
|
|
AddTask(StylesheetFileName, message, ex.LineNumber - 1, ex.LinePosition - 1, TaskType.Error); |
|
} catch(XsltException ex) { |
|
AddTask(StylesheetFileName, ex.Message, ex.LinePosition - 1, ex.LineNumber - 1, TaskType.Error); |
|
} catch(XmlException ex) { |
|
AddTask(StylesheetFileName, ex.Message, ex.LinePosition - 1, ex.LineNumber - 1, TaskType.Error); |
|
} |
|
|
|
return false; |
|
} |
|
|
|
/// <summary> |
|
/// Validates the XML in the editor against all the schemas in the |
|
/// schema manager. |
|
/// </summary> |
|
bool ValidateAgainstSchema() |
|
{ |
|
try { |
|
StringReader stringReader = new StringReader(xmlEditor.Document.TextContent); |
|
XmlTextReader xmlReader = new XmlTextReader(stringReader); |
|
xmlReader.XmlResolver = null; |
|
XmlReaderSettings settings = new XmlReaderSettings(); |
|
settings.ValidationType = ValidationType.Schema; |
|
settings.ValidationFlags = XmlSchemaValidationFlags.None; |
|
settings.XmlResolver = null; |
|
|
|
XmlSchemaCompletionData schemaData = null; |
|
try { |
|
for (int i = 0; i < XmlSchemaManager.SchemaCompletionDataItems.Count; ++i) { |
|
schemaData = XmlSchemaManager.SchemaCompletionDataItems[i]; |
|
settings.Schemas.Add(schemaData.Schema); |
|
} |
|
} catch (XmlSchemaException ex) { |
|
DisplayValidationError(schemaData.FileName, ex.Message, ex.LinePosition - 1, ex.LineNumber - 1); |
|
ShowValidationFailedMessage(); |
|
ShowErrorList(); |
|
return false; |
|
} |
|
|
|
XmlReader reader = XmlReader.Create(xmlReader, settings); |
|
|
|
XmlDocument doc = new XmlDocument(); |
|
doc.Load(reader); |
|
return true; |
|
|
|
} catch (XmlSchemaException ex) { |
|
DisplayValidationError(xmlEditor.FileName, ex.Message, ex.LinePosition - 1, ex.LineNumber - 1); |
|
} catch (XmlException ex) { |
|
DisplayValidationError(xmlEditor.FileName, ex.Message, ex.LinePosition - 1, ex.LineNumber - 1); |
|
} |
|
ShowValidationFailedMessage(); |
|
ShowErrorList(); |
|
return false; |
|
} |
|
|
|
/// <summary> |
|
/// Assumes the content in the editor is a schema and validates it using |
|
/// the XmlSchema class. This is used instead of validating against the |
|
/// XMLSchema.xsd file since it gives us better error information. |
|
/// </summary> |
|
bool ValidateSchema() |
|
{ |
|
StringReader stringReader = new StringReader(xmlEditor.Document.TextContent); |
|
XmlTextReader xmlReader = new XmlTextReader(stringReader); |
|
xmlReader.XmlResolver = null; |
|
|
|
try { |
|
XmlSchema schema = XmlSchema.Read(xmlReader, new ValidationEventHandler(SchemaValidation)); |
|
schema.Compile(new ValidationEventHandler(SchemaValidation)); |
|
} catch (XmlSchemaException ex) { |
|
DisplayValidationError(xmlEditor.FileName, ex.Message, ex.LinePosition - 1, ex.LineNumber - 1); |
|
} catch (XmlException ex) { |
|
DisplayValidationError(xmlEditor.FileName, ex.Message, ex.LinePosition - 1, ex.LineNumber - 1); |
|
} finally { |
|
xmlReader.Close(); |
|
} |
|
if (TaskService.SomethingWentWrong) { |
|
ShowValidationFailedMessage(); |
|
ShowErrorList(); |
|
return false; |
|
} |
|
return true; |
|
} |
|
|
|
void SchemaValidation(object source, ValidationEventArgs e) |
|
{ |
|
if (e.Severity == XmlSeverityType.Error) { |
|
DisplayValidationError(xmlEditor.FileName, e.Message, e.Exception.LinePosition - 1, e.Exception.LineNumber - 1); |
|
} else { |
|
DisplayValidationWarning(xmlEditor.FileName, e.Message, e.Exception.LinePosition - 1, e.Exception.LineNumber - 1); |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Displays the validation warning. |
|
/// </summary> |
|
void DisplayValidationWarning(string fileName, string message, int column, int line) |
|
{ |
|
OutputWindowWriteLine(message); |
|
AddTask(fileName, message, column, line, TaskType.Warning); |
|
} |
|
|
|
bool IsSchema { |
|
get { |
|
string extension = Path.GetExtension(xmlEditor.FileName); |
|
if (extension != null) { |
|
return String.Compare(".xsd", extension, true) == 0; |
|
} |
|
return false; |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Checks whether the element belongs to the XSD namespace. |
|
/// </summary> |
|
static bool IsXmlSchemaNamespace(XmlSchemaElement element) |
|
{ |
|
XmlQualifiedName qualifiedName = element.QualifiedName; |
|
if (qualifiedName != null) { |
|
return XmlSchemaManager.IsXmlSchemaNamespace(qualifiedName.Namespace); |
|
} |
|
return false; |
|
} |
|
|
|
/// <summary> |
|
/// If the attribute value found references another item in the schema |
|
/// return this instead of the attribute schema object. For example, if the |
|
/// user can select the attribute value and the code will work out the schema object pointed to by the ref |
|
/// or type attribute: |
|
/// |
|
/// xs:element ref="ref-name" |
|
/// xs:attribute type="type-name" |
|
/// </summary> |
|
/// <returns> |
|
/// The <paramref name="attribute"/> if no schema object was referenced. |
|
/// </returns> |
|
static XmlSchemaObject GetSchemaObjectReferenced(string xml, int index, XmlCompletionDataProvider provider, XmlSchemaCompletionData currentSchemaCompletionData, XmlSchemaElement element, XmlSchemaAttribute attribute) |
|
{ |
|
XmlSchemaObject schemaObject = null; |
|
if (IsXmlSchemaNamespace(element)) { |
|
// Find attribute value. |
|
string attributeValue = XmlParser.GetAttributeValueAtIndex(xml, index); |
|
if (attributeValue.Length == 0) { |
|
return attribute; |
|
} |
|
|
|
if (attribute.Name == "ref") { |
|
schemaObject = FindSchemaObjectReference(attributeValue, provider, currentSchemaCompletionData, element.Name); |
|
} else if (attribute.Name == "type") { |
|
schemaObject = FindSchemaObjectType(attributeValue, provider, currentSchemaCompletionData, element.Name); |
|
} |
|
} |
|
|
|
if (schemaObject != null) { |
|
return schemaObject; |
|
} |
|
return attribute; |
|
} |
|
|
|
/// <summary> |
|
/// Attempts to locate the reference name in the specified schema. |
|
/// </summary> |
|
/// <param name="name">The reference to look up.</param> |
|
/// <param name="schemaCompletionData">The schema completion data to use to |
|
/// find the reference.</param> |
|
/// <param name="elementName">The element to determine what sort of reference it is |
|
/// (e.g. group, attribute, element).</param> |
|
/// <returns><see langword="null"/> if no match can be found.</returns> |
|
static XmlSchemaObject FindSchemaObjectReference(string name, XmlCompletionDataProvider provider, XmlSchemaCompletionData schemaCompletionData, string elementName) |
|
{ |
|
QualifiedName qualifiedName = schemaCompletionData.CreateQualifiedName(name); |
|
XmlSchemaCompletionData qualifiedNameSchema = provider.FindSchema(qualifiedName.Namespace); |
|
if (qualifiedNameSchema != null) { |
|
schemaCompletionData = qualifiedNameSchema; |
|
} |
|
switch (elementName) { |
|
case "element": |
|
return schemaCompletionData.FindElement(qualifiedName); |
|
case "attribute": |
|
return schemaCompletionData.FindAttribute(qualifiedName.Name); |
|
case "group": |
|
return schemaCompletionData.FindGroup(qualifiedName.Name); |
|
case "attributeGroup": |
|
return schemaCompletionData.FindAttributeGroup(qualifiedName.Name); |
|
} |
|
return null; |
|
} |
|
|
|
/// <summary> |
|
/// Attempts to locate the type name in the specified schema. |
|
/// </summary> |
|
/// <param name="name">The type to look up.</param> |
|
/// <param name="schemaCompletionData">The schema completion data to use to |
|
/// find the type.</param> |
|
/// <param name="elementName">The element to determine what sort of type it is |
|
/// (e.g. group, attribute, element).</param> |
|
/// <returns><see langword="null"/> if no match can be found.</returns> |
|
static XmlSchemaObject FindSchemaObjectType(string name, XmlCompletionDataProvider provider, XmlSchemaCompletionData schemaCompletionData, string elementName) |
|
{ |
|
QualifiedName qualifiedName = schemaCompletionData.CreateQualifiedName(name); |
|
XmlSchemaCompletionData qualifiedNameSchema = provider.FindSchema(qualifiedName.Namespace); |
|
if (qualifiedNameSchema != null) { |
|
schemaCompletionData = qualifiedNameSchema; |
|
} |
|
switch (elementName) { |
|
case "element": |
|
return schemaCompletionData.FindComplexType(qualifiedName); |
|
case "attribute": |
|
return schemaCompletionData.FindSimpleType(qualifiedName.Name); |
|
} |
|
return null; |
|
} |
|
|
|
/// <summary> |
|
/// Converts a set of schemas to a string array, each array item |
|
/// contains the schema converted to a string. |
|
/// </summary> |
|
string[] GetSchemas(XmlSchemaSet schemaSet) |
|
{ |
|
List<string> schemas = new List<string>(); |
|
foreach (XmlSchema schema in schemaSet.Schemas()) { |
|
using (EncodedStringWriter writer = new EncodedStringWriter(xmlEditor.TextEditorProperties.Encoding)) { |
|
using (XmlTextWriter xmlWriter = CreateXmlTextWriter(writer)) { |
|
schema.Write(xmlWriter); |
|
schemas.Add(writer.ToString()); |
|
} |
|
} |
|
} |
|
return schemas.ToArray(); |
|
} |
|
|
|
/// <summary> |
|
/// Gets the edit actions for the xml editor from the addin tree. |
|
/// </summary> |
|
IEditAction[] GetEditActions() |
|
{ |
|
return (IEditAction[])(AddInTree.BuildItems(editActionsPath, this, false).ToArray(typeof(IEditAction))); |
|
} |
|
} |
|
}
|
|
|