* Makefile.am:
[monodevelop.git] / main / src / addins / MonoDevelop.XmlEditor / MonoDevelop.XmlEditor / XmlTextEditorExtension.cs
blob57669ca2a26a0ec4bd4ac1c05ee684c93b72cb6d
1 //
2 // XmlTextEditorExtension.cs
3 //
4 // Authors:
5 // Matt Ward
6 // Michael Hutchinson <mhutchinson@novell.com>
7 //
8 // Copyright:
9 // (C) 2007 Matt Ward
10 // (C) 2008 Novell, Inc (http://www.novell.com)
11 //
12 // License:
13 // Derived from LGPL files (Matt Ward)
14 // All code since then is MIT/X11
16 using System;
17 using System.Linq;
18 using System.Collections.Generic;
19 using System.Xml;
20 using System.Xml.Schema;
22 using MonoDevelop.Core;
23 using MonoDevelop.Components.Commands;
24 using MonoDevelop.Projects.Gui;
25 using MonoDevelop.Projects.Gui.Completion;
26 using MonoDevelop.Ide.Gui.Content;
27 using MonoDevelop.XmlEditor.Completion;
28 using MonoDevelop.Xml.StateEngine;
30 namespace MonoDevelop.XmlEditor
34 public class XmlTextEditorExtension : MonoDevelop.XmlEditor.Gui.BaseXmlEditorExtension
36 const string TextXmlMimeType = "text/xml";
37 const string ApplicationXmlMimeType = "application/xml";
38 string stylesheetFileName;
39 XmlSchemaCompletionData defaultSchemaCompletionData;
40 string defaultNamespacePrefix;
41 InferredXmlCompletionProvider inferredCompletionData;
42 bool inferenceQueued = false;
44 // bool showSchemaAnnotation;
46 public XmlTextEditorExtension() : base ()
50 public override bool ExtendsEditor (MonoDevelop.Ide.Gui.Document doc, IEditableTextBuffer editor)
52 if (doc == null)
53 return false;
54 return IsFileNameHandled (doc.Name);
57 protected override IEnumerable<string> SupportedExtensions {
58 get { throw new System.InvalidOperationException (); }
62 public override void Initialize ()
64 base.Initialize ();
65 XmlEditorAddInOptions.PropertyChanged += XmlEditorPropertyChanged;
66 XmlSchemaManager.UserSchemaAdded += UserSchemaAdded;
67 XmlSchemaManager.UserSchemaRemoved += UserSchemaRemoved;
68 SetInitialValues();
70 MonoDevelop.SourceEditor.SourceEditorView view =
71 Document.GetContent<MonoDevelop.SourceEditor.SourceEditorView> ();
72 if (view != null && view.Document.SyntaxMode == null) {
73 Mono.TextEditor.Highlighting.SyntaxMode mode =
74 Mono.TextEditor.Highlighting.SyntaxModeService.GetSyntaxMode (ApplicationXmlMimeType);
75 if (mode != null)
76 view.Document.SyntaxMode = mode;
77 else
78 LoggingService.LogWarning ("XmlTextEditorExtension could not get SyntaxMode for mimetype '"
79 + ApplicationXmlMimeType + "'.");
83 bool disposed;
84 public override void Dispose()
86 if (!disposed) {
87 disposed = false;
88 XmlEditorAddInOptions.PropertyChanged -= XmlEditorPropertyChanged;
89 XmlSchemaManager.UserSchemaAdded -= UserSchemaAdded;
90 XmlSchemaManager.UserSchemaRemoved -= UserSchemaRemoved;
91 base.Dispose ();
95 #region Code completion
97 // IEditableTextBuffer GetBuffer ()
98 // {
99 // IEditableTextBuffer buf = Document.GetContent<IEditableTextBuffer> ();
100 // System.Diagnostics.Debug.Assert (buf != null);
101 // return buf;
102 // }
104 XmlElementPath GetCurrentPath ()
106 return ConvertPath (Tracker.Engine.Nodes.OfType<XElement> ().Reverse ());
109 static XmlElementPath ConvertPath (IEnumerable<XElement> path)
111 XmlElementPath elementPath = new XmlElementPath ();
112 var namespaces = new Dictionary<string, string> ();
113 string defaultNamespace = null;
114 foreach (XElement el in path) {
115 foreach (XAttribute att in el.Attributes) {
116 if (att.Name.HasPrefix) {
117 if (att.Name.Prefix == "xmlns")
118 namespaces [att.Name.Name] = att.Value;
119 } else {
120 if (att.Name.Name == "xmlns")
121 defaultNamespace = att.Value;
124 string ns = null;
125 if (el.Name.HasPrefix)
126 namespaces.TryGetValue (el.Name.Prefix, out ns);
127 else
128 ns = defaultNamespace;
129 QualifiedName qn = new QualifiedName (el.Name.Name, ns, el.Name.Prefix ?? String.Empty);
130 elementPath.Elements.Add (qn);
132 return elementPath;
135 protected override void GetElementCompletions (CompletionDataList list)
137 XmlElementPath path = GetCurrentPath ();
138 if (path.Elements.Count > 0) {
139 IXmlCompletionProvider schema = FindSchema (path);
140 if (schema == null)
141 schema = inferredCompletionData;
142 if (schema != null) {
143 ICompletionData[] completionData = schema.GetChildElementCompletionData (path);
144 if (completionData != null)
145 list.AddRange (completionData);
147 } else if (defaultSchemaCompletionData != null) {
148 list.AddRange (defaultSchemaCompletionData.GetElementCompletionData (defaultNamespacePrefix));
149 } else if (inferredCompletionData != null) {
150 list.AddRange (inferredCompletionData.GetElementCompletionData ());
154 protected override void GetAttributeCompletions (CompletionDataList list, IAttributedXObject attributedOb,
155 Dictionary<string, string> existingAtts)
157 XmlElementPath path = GetCurrentPath ();
158 if (path.Elements.Count > 0) {
159 IXmlCompletionProvider schema = FindSchema (path);
160 if (schema == null)
161 schema = inferredCompletionData;
162 if (schema != null) {
163 ICompletionData[] completionData = schema.GetAttributeCompletionData (path);
164 if (completionData != null)
165 list.AddRange (completionData);
170 protected override void GetAttributeValueCompletions (CompletionDataList list, IAttributedXObject attributedOb,
171 XAttribute att)
173 XmlElementPath path = GetCurrentPath ();
174 if (path.Elements.Count > 0) {
175 XmlSchemaCompletionData schema = FindSchema (path);
176 if (schema != null) {
177 ICompletionData[] completionData = schema.GetAttributeValueCompletionData (path, att.Name.FullName);
178 if (completionData != null)
179 list.AddRange (completionData);
184 #endregion
186 #region From XmlCompletionDataProvider.cs
188 public XmlSchemaCompletionData FindSchemaFromFileName (string fileName)
190 return XmlSchemaManager.SchemaCompletionDataItems.GetSchemaFromFileName (fileName);
193 public XmlSchemaCompletionData FindSchema (string namespaceUri)
195 return XmlSchemaManager.SchemaCompletionDataItems[namespaceUri];
198 public XmlSchemaCompletionData FindSchema (XmlElementPath path)
200 return FindSchema (XmlSchemaManager.SchemaCompletionDataItems, path);
203 /// <summary>
204 /// Finds the schema given the xml element path.
205 /// </summary>
206 public XmlSchemaCompletionData FindSchema (IXmlSchemaCompletionDataCollection schemaCompletionDataItems, XmlElementPath path)
208 if (path.Elements.Count > 0) {
209 string namespaceUri = path.Elements[0].Namespace;
210 if (namespaceUri.Length > 0) {
211 return schemaCompletionDataItems[namespaceUri];
212 } else if (defaultSchemaCompletionData != null) {
214 // Use the default schema namespace if none
215 // specified in a xml element path, otherwise
216 // we will not find any attribute or element matches
217 // later.
218 foreach (QualifiedName name in path.Elements) {
219 if (name.Namespace.Length == 0) {
220 name.Namespace = defaultSchemaCompletionData.NamespaceUri;
223 return defaultSchemaCompletionData;
226 return null;
229 #endregion
231 #region Schema resolution
233 /// <summary>
234 /// Gets the XmlSchemaObject that defines the currently selected xml element or attribute.
235 /// </summary>
236 /// <param name="currentSchemaCompletionData">This is the schema completion data for the schema currently being
237 /// displayed. This can be null if the document is not a schema.</param>
238 public XmlSchemaObject GetSchemaObjectSelected (XmlSchemaCompletionData currentSchemaCompletionData)
240 // Find element under cursor.
241 XmlElementPath path = GetCurrentPath ();
243 //attribute name under cursor, if valid
244 string attributeName = null;
245 XAttribute xatt = Tracker.Engine.Nodes.Peek (0) as XAttribute;
246 if (xatt != null) {
247 XName xattName = xatt.Name;
248 if (Tracker.Engine.CurrentState is XmlNameState) {
249 xattName = GetCompleteName ();
251 attributeName = xattName.FullName;
254 // Find schema definition object.
255 XmlSchemaCompletionData schemaCompletionData = FindSchema (path);
256 XmlSchemaObject schemaObject = null;
257 if (schemaCompletionData != null) {
258 XmlSchemaElement element = schemaCompletionData.FindElement(path);
259 schemaObject = element;
260 if (element != null) {
261 if (attributeName.Length > 0) {
262 XmlSchemaAttribute attribute = schemaCompletionData.FindAttribute(element, attributeName);
263 if (attribute != null) {
264 if (currentSchemaCompletionData != null) {
265 schemaObject = GetSchemaObjectReferenced (currentSchemaCompletionData, element, attribute);
266 } else {
267 schemaObject = attribute;
271 return schemaObject;
274 return null;
277 /// <summary>
278 /// If the attribute value found references another item in the schema
279 /// return this instead of the attribute schema object. For example, if the
280 /// user can select the attribute value and the code will work out the schema object pointed to by the ref
281 /// or type attribute:
283 /// xs:element ref="ref-name"
284 /// xs:attribute type="type-name"
285 /// </summary>
286 /// <returns>
287 /// The <paramref name="attribute"/> if no schema object was referenced.
288 /// </returns>
289 XmlSchemaObject GetSchemaObjectReferenced (XmlSchemaCompletionData currentSchemaCompletionData, XmlSchemaElement element, XmlSchemaAttribute attribute)
291 XmlSchemaObject schemaObject = null;
292 if (IsXmlSchemaNamespace(element)) {
293 // Find attribute value.
294 //fixme implement
295 string attributeValue = "";// XmlParser.GetAttributeValueAtIndex(xml, index);
296 if (attributeValue.Length == 0) {
297 return attribute;
300 if (attribute.Name == "ref") {
301 schemaObject = FindSchemaObjectReference(attributeValue, currentSchemaCompletionData, element.Name);
302 } else if (attribute.Name == "type") {
303 schemaObject = FindSchemaObjectType(attributeValue, currentSchemaCompletionData, element.Name);
307 if (schemaObject != null) {
308 return schemaObject;
310 return attribute;
313 /// <summary>
314 /// Checks whether the element belongs to the XSD namespace.
315 /// </summary>
316 static bool IsXmlSchemaNamespace (XmlSchemaElement element)
318 XmlQualifiedName qualifiedName = element.QualifiedName;
319 if (qualifiedName != null) {
320 return XmlSchemaManager.IsXmlSchemaNamespace (qualifiedName.Namespace);
322 return false;
325 /// <summary>
326 /// Attempts to locate the reference name in the specified schema.
327 /// </summary>
328 /// <param name="name">The reference to look up.</param>
329 /// <param name="schemaCompletionData">The schema completion data to use to
330 /// find the reference.</param>
331 /// <param name="elementName">The element to determine what sort of reference it is
332 /// (e.g. group, attribute, element).</param>
333 /// <returns><see langword="null"/> if no match can be found.</returns>
334 XmlSchemaObject FindSchemaObjectReference(string name, XmlSchemaCompletionData schemaCompletionData, string elementName)
336 QualifiedName qualifiedName = schemaCompletionData.CreateQualifiedName(name);
337 XmlSchemaCompletionData qualifiedNameSchema = FindSchema(qualifiedName.Namespace);
338 if (qualifiedNameSchema != null) {
339 schemaCompletionData = qualifiedNameSchema;
341 switch (elementName) {
342 case "element":
343 return schemaCompletionData.FindElement(qualifiedName);
344 case "attribute":
345 return schemaCompletionData.FindAttribute(qualifiedName.Name);
346 case "group":
347 return schemaCompletionData.FindGroup(qualifiedName.Name);
348 case "attributeGroup":
349 return schemaCompletionData.FindAttributeGroup(qualifiedName.Name);
351 return null;
354 /// <summary>
355 /// Attempts to locate the type name in the specified schema.
356 /// </summary>
357 /// <param name="name">The type to look up.</param>
358 /// <param name="schemaCompletionData">The schema completion data to use to
359 /// find the type.</param>
360 /// <param name="elementName">The element to determine what sort of type it is
361 /// (e.g. group, attribute, element).</param>
362 /// <returns><see langword="null"/> if no match can be found.</returns>
363 XmlSchemaObject FindSchemaObjectType(string name, XmlSchemaCompletionData schemaCompletionData, string elementName)
365 QualifiedName qualifiedName = schemaCompletionData.CreateQualifiedName(name);
366 XmlSchemaCompletionData qualifiedNameSchema = FindSchema(qualifiedName.Namespace);
367 if (qualifiedNameSchema != null) {
368 schemaCompletionData = qualifiedNameSchema;
370 switch (elementName) {
371 case "element":
372 return schemaCompletionData.FindComplexType(qualifiedName);
373 case "attribute":
374 return schemaCompletionData.FindSimpleType(qualifiedName.Name);
376 return null;
379 #endregion
381 #region Settings handling
383 void SetDefaultSchema (string fileName)
385 if (fileName == null) {
386 return;
388 string extension = System.IO.Path.GetExtension (fileName).ToLower ();
389 defaultSchemaCompletionData = XmlSchemaManager.GetSchemaCompletionData (extension);
390 if (defaultSchemaCompletionData != null)
391 inferredCompletionData = null;
392 else
393 QueueInference ();
394 defaultNamespacePrefix = XmlSchemaManager.GetNamespacePrefix (extension);
397 /// Updates the default schema association since the schema may have been added.
398 void UserSchemaAdded (object source, EventArgs e)
400 SetDefaultSchema (Document.Name);
403 // Updates the default schema association since the schema may have been removed.
404 void UserSchemaRemoved (object source, EventArgs e)
406 SetDefaultSchema (Document.Name);
409 void XmlEditorPropertyChanged (object sender, PropertyChangedEventArgs args)
411 switch (args.Key) {
412 case "AutoCompleteElements":
413 AutoCompleteClosingTags = XmlEditorAddInOptions.AutoCompleteElements;
414 break;
415 case "ShowSchemaAnnotation":
416 // showSchemaAnnotation = XmlEditorAddInOptions.ShowSchemaAnnotation;
417 break;
418 default:
419 string extension = System.IO.Path.GetExtension (Document.Name).ToLower ();
420 if (args.Key == extension) {
421 SetDefaultSchema (Document.Name);
422 } else {
423 LoggingService.LogError ("Unhandled property change in XmlTextEditorExtension: " + args.Key);
425 break;
429 void SetInitialValues()
431 // showSchemaAnnotation = XmlEditorAddInOptions.ShowSchemaAnnotation;
432 AutoCompleteClosingTags = XmlEditorAddInOptions.AutoCompleteElements;
433 SetDefaultSchema (Document.Name);
436 #endregion
438 #region Stylesheet handling
440 /// <summary>
441 /// Gets or sets the stylesheet associated with this xml file.
442 /// </summary>
443 public string StylesheetFileName {
444 get { return stylesheetFileName; }
445 set { stylesheetFileName = value; }
448 #endregion
450 #region Filetype/schema detection
452 public bool IsSchema {
453 get {
454 string extension = System.IO.Path.GetExtension (FileName);
455 if (extension != null)
456 return String.Compare (extension, ".xsd", true) == 0;
457 return false;
461 /// <summary>
462 /// Determines whether the file can be displayed by
463 /// the xml editor.
464 /// </summary>
465 public static bool IsFileNameHandled (string fileName)
467 if (fileName == null)
468 return false;
470 if (System.IO.Path.IsPathRooted (fileName)) {
471 string vfsname = fileName.Replace ("%", "%25").Replace ("#", "%23").Replace ("?", "%3F");
472 string mimeType = MonoDevelop.Core.Gui.Services.PlatformService.GetMimeTypeForUri (vfsname);
473 if (IsMimeTypeHandled (mimeType))
474 return true;
477 return XmlFileExtensions.IsXmlFileExtension (System.IO.Path.GetExtension (fileName));
480 public static bool IsMimeTypeHandled (string mimeType)
482 return (mimeType != null && (mimeType == TextXmlMimeType || mimeType == ApplicationXmlMimeType));
485 #endregion
487 #region Smart indent
489 public override bool KeyPress (Gdk.Key key, char keyChar, Gdk.ModifierType modifier)
491 bool result;
493 if (TextEditorProperties.IndentStyle == IndentStyle.Smart && key == Gdk.Key.Return) {
494 result = base.KeyPress (key, keyChar, modifier);
495 SmartIndentLine (Editor.CursorLine);
496 return result;
498 return base.KeyPress (key, keyChar, modifier);
501 void SmartIndentLine (int line)
503 //FIXME: implement this
506 // string GetLineIndent (int line)
507 // {
508 // string indent = string.Empty;
509 // int start = Editor.GetPositionFromLineColumn (line, 1);
510 // int i = start;
511 // while (i < Editor.TextLength) {
512 // char c = Editor.GetCharAt (i);
513 // if (c == '\n' || c == '\r')
514 // break;
515 // if (!char.IsWhiteSpace (c))
516 // break;
517 // i++;
518 // }
519 // if (i > 0)
520 // indent = Editor.GetText (start, i);
521 // return indent;
522 // }
524 //gets the indent of the line containing this position, up to the position index
525 string GetPositionIndent (int position)
527 int indentEnd = position;
528 int i = position - 1;
529 while (i > 0) {
530 char c = Editor.GetCharAt (i);
531 if (c == '\n' || c == '\r')
532 return Editor.GetText (i + 1, indentEnd);
533 if (!char.IsWhiteSpace (c))
534 indentEnd--;
535 i--;
537 return null;
540 #endregion
542 #region Command handlers
544 [CommandUpdateHandler (MonoDevelop.Ide.Commands.EditCommands.ToggleCodeComment)]
545 protected void ToggleCodeCommentCommandUpdate (CommandInfo info)
547 info.Enabled = false;
550 [CommandHandler (MonoDevelop.Ide.Commands.EditCommands.ToggleCodeComment)]
551 public void ToggleCodeCommentCommand ()
553 //FIXME: implement
556 [CommandHandler (Commands.Format)]
557 public void FormatCommand ()
559 MonoDevelop.Ide.Gui.IdeApp.Services.TaskService.ClearExceptCommentTasks ();
561 using (IProgressMonitor monitor = XmlEditorService.GetMonitor ()) {
562 bool selection = (Editor.SelectionEndPosition - Editor.SelectionStartPosition) > 0;
563 string xml = selection? Editor.SelectedText : Editor.Text;
564 XmlDocument doc = XmlEditorService.ValidateWellFormedness (monitor, xml, FileName);
565 if (doc == null)
566 return;
568 //if there's a line indent at the current location, prepend that to all new lines
569 string extraIndent = null;
570 if (selection)
571 extraIndent = GetPositionIndent (Editor.SelectionStartPosition);
573 string formattedXml = XmlEditorService.IndentedFormat (xml);
575 //convert newlines and prepend extra indents to each line if needed
576 bool nonNativeNewline = (Editor.NewLine != Environment.NewLine);
577 bool hasExtraIndent = !string.IsNullOrEmpty (extraIndent);
578 if (hasExtraIndent || nonNativeNewline) {
579 System.Text.StringBuilder builder = new System.Text.StringBuilder (formattedXml);
581 if (nonNativeNewline)
582 builder.Replace (Environment.NewLine, Editor.NewLine);
584 if (hasExtraIndent) {
585 builder.Replace (Editor.NewLine, Editor.NewLine + extraIndent);
586 if (formattedXml.EndsWith (Environment.NewLine))
587 builder.Remove (builder.Length - 1 - extraIndent.Length, extraIndent.Length);
589 formattedXml = builder.ToString ();
592 Editor.BeginAtomicUndo ();
593 if (selection) {
594 Editor.SelectedText = formattedXml;
595 } else {
596 Editor.DeleteText (0, Editor.TextLength);
597 Editor.InsertText (0, formattedXml);
599 Editor.EndAtomicUndo ();
603 [CommandHandler (Commands.CreateSchema)]
604 public void CreateSchemaCommand ()
606 try {
607 MonoDevelop.Ide.Gui.IdeApp.Services.TaskService.ClearExceptCommentTasks ();
608 string xml = Editor.Text;
609 using (IProgressMonitor monitor = XmlEditorService.GetMonitor ()) {
610 XmlDocument doc = XmlEditorService.ValidateWellFormedness (monitor, xml, FileName);
611 if (doc == null)
612 return;
613 monitor.BeginTask (GettextCatalog.GetString ("Creating schema..."), 0);
614 try {
615 string schema = XmlEditorService.CreateSchema (xml);
616 string fileName = XmlEditorService.GenerateFileName (FileName, "{0}.xsd");
617 MonoDevelop.Ide.Gui.IdeApp.Workbench.NewDocument (fileName, "application/xml", schema);
618 monitor.ReportSuccess (GettextCatalog.GetString ("Schema created."));
619 } catch (Exception ex) {
620 string msg = GettextCatalog.GetString ("Error creating XML schema.");
621 LoggingService.LogError (msg, ex);
622 monitor.ReportError (msg, ex);
625 } catch (Exception ex) {
626 MonoDevelop.Core.Gui.MessageService.ShowError(ex.Message);
630 [CommandHandler (Commands.OpenStylesheet)]
631 public void OpenStylesheetCommand ()
633 if (!string.IsNullOrEmpty (stylesheetFileName)) {
634 try {
635 MonoDevelop.Ide.Gui.IdeApp.Workbench.OpenDocument (stylesheetFileName);
636 } catch (Exception ex) {
637 MonoDevelop.Core.LoggingService.LogError ("Could not open document.", ex);
638 MonoDevelop.Core.Gui.MessageService.ShowException (ex, "Could not open document.");
643 [CommandUpdateHandler (Commands.OpenStylesheet)]
644 public void UpdateOpenStylesheetCommand (CommandInfo info)
646 info.Enabled = !string.IsNullOrEmpty (stylesheetFileName);
649 [CommandHandler (Commands.GoToSchemaDefinition)]
650 public void GoToSchemaDefinitionCommand ()
652 try {
653 //try to resolve the schema
654 XmlSchemaCompletionData currentSchemaCompletionData = FindSchemaFromFileName (FileName);
655 XmlSchemaObject schemaObject = GetSchemaObjectSelected (currentSchemaCompletionData);
657 // Open schema if resolved
658 if (schemaObject != null && schemaObject.SourceUri != null && schemaObject.SourceUri.Length > 0) {
659 string schemaFileName = schemaObject.SourceUri.Replace ("file:/", String.Empty);
660 MonoDevelop.Ide.Gui.IdeApp.Workbench.OpenDocument (
661 schemaFileName,
662 Math.Max (1, schemaObject.LineNumber),
663 Math.Max (1, schemaObject.LinePosition), true);
665 } catch (Exception ex) {
666 MonoDevelop.Core.LoggingService.LogError ("Could not open document.", ex);
667 MonoDevelop.Core.Gui.MessageService.ShowException (ex, "Could not open document.");
671 [CommandHandler (Commands.Validate)]
672 public void ValidateCommand ()
674 MonoDevelop.Ide.Gui.IdeApp.Services.TaskService.ClearExceptCommentTasks ();
675 using (IProgressMonitor monitor = XmlEditorService.GetMonitor()) {
676 if (IsSchema)
677 XmlEditorService.ValidateSchema (monitor, Editor.Text, FileName);
678 else
679 XmlEditorService.ValidateXml (monitor, Editor.Text, FileName);
683 [CommandHandler (Commands.AssignStylesheet)]
684 public void AssignStylesheetCommand ()
686 // Prompt user for filename.
687 string fileName = XmlEditorService.BrowseForStylesheetFile ();
688 if (!string.IsNullOrEmpty (stylesheetFileName))
689 stylesheetFileName = fileName;
692 [CommandHandler (Commands.RunXslTransform)]
693 public void RunXslTransformCommand ()
695 if (string.IsNullOrEmpty (stylesheetFileName)) {
696 stylesheetFileName = XmlEditorService.BrowseForStylesheetFile ();
697 if (string.IsNullOrEmpty (stylesheetFileName))
698 return;
701 using (IProgressMonitor monitor = XmlEditorService.GetMonitor()) {
702 try {
703 string xsltContent;
704 try {
705 xsltContent = GetFileContent (stylesheetFileName);
706 } catch (System.IO.IOException) {
707 monitor.ReportError (
708 GettextCatalog.GetString ("Error reading file '{0}'.", stylesheetFileName), null);
709 return;
711 System.Xml.Xsl.XslTransform xslt =
712 XmlEditorService.ValidateStylesheet (monitor, xsltContent, stylesheetFileName);
713 if (xslt == null)
714 return;
716 XmlDocument doc = XmlEditorService.ValidateXml (monitor, Editor.Text, FileName);
717 if (doc == null)
718 return;
720 string newFileName = XmlEditorService.GenerateFileName (FileName, "-transformed{0}.xml");
722 monitor.BeginTask (GettextCatalog.GetString ("Executing transform..."), 1);
723 using (XmlTextWriter output = XmlEditorService.CreateXmlTextWriter()) {
724 xslt.Transform (doc, null, output);
725 MonoDevelop.Ide.Gui.IdeApp.Workbench.NewDocument (
726 newFileName, "application/xml", output.ToString ());
728 monitor.ReportSuccess (GettextCatalog.GetString ("Transform completed."));
729 monitor.EndTask ();
730 } catch (Exception ex) {
731 string msg = GettextCatalog.GetString ("Could not run transform.");
732 monitor.ReportError (msg, ex);
733 monitor.EndTask ();
738 string GetFileContent (string fileName)
740 MonoDevelop.Projects.Text.IEditableTextFile tf =
741 MonoDevelop.DesignerSupport.OpenDocumentFileProvider.Instance.GetEditableTextFile (fileName);
742 if (tf != null)
743 return tf.Text;
744 System.IO.StreamReader reader = new System.IO.StreamReader (fileName, true);
745 return reader.ReadToEnd();
748 #endregion
750 void QueueInference ()
752 XmlParsedDocument doc = this.CU as XmlParsedDocument;
753 if (defaultSchemaCompletionData != null || doc == null || doc.XDocument == null || inferenceQueued)
754 return;
755 if (inferredCompletionData == null
756 || (doc.ParseTime - inferredCompletionData.TimeStamp).TotalSeconds >= 5
757 && doc.Errors.Count <= inferredCompletionData.ErrorCount)
759 inferenceQueued = true;
760 System.Threading.ThreadPool.QueueUserWorkItem (delegate {
761 InferredXmlCompletionProvider newData = new InferredXmlCompletionProvider ();
762 newData.Populate (doc.XDocument);
763 newData.TimeStamp = DateTime.Now;
764 newData.ErrorCount = doc.Errors.Count;
765 this.inferenceQueued = false;
766 this.inferredCompletionData = newData;
771 protected override void OnParsedDocumentUpdated ()
773 QueueInference ();
774 base.OnParsedDocumentUpdated ();