Browse Source
- fixed XPath Query Pad - added documentation and AssemblyInfo.cs from old XmlEditor git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/XmlEditor@4198 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61shortcuts
20 changed files with 319 additions and 135 deletions
@ -0,0 +1,175 @@
@@ -0,0 +1,175 @@
|
||||
Xml Intellisense |
||||
---------------- |
||||
|
||||
In order to be able to provide intellisense for an xml document we need a schema. From the schema we can determine an element's attributes and its child elements. Without resorting to writing our own xml schema parser, can we retrieve this information from the schema? |
||||
|
||||
XmlSchema class |
||||
--------------- |
||||
|
||||
The .Net framework provides us with the XmlSchema class. It provides us with two methods that of interest to us when reading rather than creating an xml schema. |
||||
|
||||
1) Read - Reads an XML Schema definition language (XSD) schema. |
||||
|
||||
2) Compile - Compiles the XML Schema definition language (XSD) Schema Object Model (SOM) into schema information for validation. Used to check the syntactic and semantic structure of the programmatically-built SOM. Semantic validation checking is performed during compilation. |
||||
|
||||
Let us first look at the Read method and see what we can get from it. |
||||
|
||||
The read method seems to do a first parse of the schema, the XmlSchema.Elements property is not populated, about the only thing that is populated is the Items property, which seems to be pretty much a mirror image of what is in the xsd file. |
||||
|
||||
Quickstart sample from Microsoft |
||||
-------------------------------- |
||||
|
||||
XmlSchemaObjectModel sample |
||||
|
||||
http://go.microsoft.com/fwlink/?linkid=3268&url=/quickstart/howto/doc/XML/XmlSchemaObjectModel.aspx |
||||
|
||||
A sample provided by Microsoft adds two schemas to an XmlSchemaCollection, outputs the schema xsd based on what was read in, then generates an xml documentrepresentative of the read in schema. |
||||
|
||||
XmlNameTable myXmlNameTable = new NameTable(); |
||||
XmlSchemaCollection myXmlSchemaCollection = new XmlSchemaCollection(myXmlNameTable); |
||||
myXmlSchemaCollection.Add(null, "books.xsd"); |
||||
myXmlSchemaCollection.Add(null, "poschema.xsd"); |
||||
|
||||
foreach(XmlSchema myTempXmlSchema in myXmlSchemaCollection) |
||||
{ |
||||
myXmlSchema = myTempXmlSchema; |
||||
|
||||
// Write out the various schema parts |
||||
WriteXSDSchema(); |
||||
|
||||
// Write out an example of the XML for the schema |
||||
WriteExample(); |
||||
|
||||
} |
||||
|
||||
|
||||
void WriteXSDSchema() |
||||
{ |
||||
myXmlTextWriter.WriteStartElement("schema", XmlSchema.Namespace); |
||||
myXmlTextWriter.WriteAttributeString("targetNamespace", myXmlSchema.TargetNamespace); |
||||
foreach(XmlSchemaInclude include in myXmlSchema.Includes) |
||||
{ |
||||
myXmlTextWriter.WriteStartElement("include", XmlSchema.Namespace); |
||||
myXmlTextWriter.WriteAttributeString("schemaLocation", include.SchemaLocation); |
||||
myXmlTextWriter.WriteEndElement(); |
||||
} |
||||
|
||||
foreach(object item in myXmlSchema.Items) |
||||
{ |
||||
if (item is XmlSchemaAttribute) |
||||
WriteXmlSchemaAttribute((XmlSchemaAttribute)item); //attribute |
||||
else if (item is XmlSchemaComplexType) |
||||
WriteXmlSchemaComplexType((XmlSchemaComplexType)item); //complexType |
||||
else if (item is XmlSchemaSimpleType) |
||||
WriteXmlSchemaSimpleType((XmlSchemaSimpleType)item); //simpleType |
||||
else if (item is XmlSchemaElement) |
||||
WriteXmlSchemaElement((XmlSchemaElement)item); //element |
||||
else if (item is XmlSchemaAnnotation) |
||||
WriteXmlSchemaAnnotation((XmlSchemaAnnotation)item); //annotation |
||||
else if (item is XmlSchemaAttributeGroup) |
||||
WriteXmlSchemaAttributeGroup((XmlSchemaAttributeGroup)item); //attributeGroup |
||||
else if (item is XmlSchemaNotation) |
||||
WriteXmlSchemaNotation((XmlSchemaNotation)item); //notation |
||||
else if (item is XmlSchemaGroup) |
||||
WriteXmlSchemaGroup((XmlSchemaGroup)item); //group |
||||
else |
||||
Console.WriteLine("Not Implemented."); |
||||
} |
||||
myXmlTextWriter.WriteEndElement(); |
||||
} |
||||
|
||||
// Write out the example of the XSD usage |
||||
void WriteExample() |
||||
{ |
||||
foreach(XmlSchemaElement element in myXmlSchema.Elements.Values) |
||||
WriteExampleElement(element); |
||||
} |
||||
|
||||
// Write some example elements |
||||
void WriteExampleElement(XmlSchemaElement element) |
||||
{ |
||||
myXmlTextWriter.WriteStartElement(element.QualifiedName.Name, element.QualifiedName.Namespace); |
||||
if (element.ElementType is XmlSchemaComplexType) |
||||
{ |
||||
XmlSchemaComplexType type = (XmlSchemaComplexType)element.ElementType; |
||||
if (type.ContentModel != null) |
||||
Console.WriteLine("Not Implemented for this ContentModel"); |
||||
WriteExampleAttributes(type.Attributes); |
||||
WriteExampleParticle(type.Particle); |
||||
} |
||||
else |
||||
WriteExampleValue(element.ElementType); |
||||
|
||||
myXmlTextWriter.WriteEndElement(); |
||||
} |
||||
|
||||
Now how does this work? The WriteExample code iterates through the XmlSchema.Elements.Values collection and outputs some data for each XmlSchemaElement. The Elements property is not generated when you only do an XmlSchema.Read. What is actually happening is that the schema is being compiled aswell. I stumbled across this not using Reflector, but when changing the sample code to read in NAnt's 0.84 schema. Reading in NAnt-0.84.xsd the code threw an exception since one of the types (formatter) was defined twice, even though the schema is valid as far as I can tell. The exception was thrown at the line |
||||
|
||||
myXmlSchemaCollection.Add(null, "nant-0.84.xsd"); |
||||
|
||||
The exception call stack showed that XmlSchemaCollection.Add method calls XmlSchema.Compile. |
||||
|
||||
So it looks like we need to compile the XmlSchema object to get it to do a second parse. |
||||
|
||||
Xhtml1-Strict |
||||
------------- |
||||
|
||||
Fun and games getting this to load in the XmlSchema object. |
||||
|
||||
First, set the XmlResolver to null on the XmlTextReader. If this is not done the reader tries to look for referenced DTDs in the assembly folder. When the resolver is set to null it looks for the DTDs in the same folder as the .xsd itself which seems more reasonable. |
||||
|
||||
XmlSchema throws an exception because the xhtml1-strict.xsd redefines the xml namespace via the string xmlns:xml="http://www.w3.org/XML/1998/namespace" at the top of the file. According to the w3 spec this is valid, but the XmlSchema class does not like it. |
||||
|
||||
|
||||
Xml Editor handling property changes |
||||
------------------------------------ |
||||
|
||||
The properties are changed from inside SharpDevelop. Options are: |
||||
|
||||
1) Directly access the SharpDevelop properties each time the control is about to do something. |
||||
2) Control exposes properties which need to be changed via another object, not the editor, |
||||
when they have changed. |
||||
3) Control exposes a property object with a defined interface which the user of the control |
||||
can set. This object is checked whenever the control attempts to do something. This |
||||
object can access the SharpDevelop properties. |
||||
|
||||
I want to keep the Xml Editor control only dependent on the SharpDevelop Text Editor. This rules out option 1. |
||||
|
||||
|
||||
Schemas |
||||
------- |
||||
|
||||
System schemas |
||||
-------------- |
||||
|
||||
System schemas will live in the C:\Program Files\SharpDevelop\data\schemas folder. |
||||
|
||||
The PropertyService gives us a DataDirectory property which usually points to C:\Program Files\SharpDevelop\data so we can use this. |
||||
|
||||
If the folder does not exist it is not created since access to C:\Program Files can be restricted. |
||||
|
||||
User schemas |
||||
------------ |
||||
|
||||
User schemas will live in C:\Documents and Settings\web\Application Data\.ICSharpCode\SharpDevelop\schemas folder. |
||||
|
||||
The PropertyService gives us a ConfigDirectory which points to the parent of the above folder (i.e. SharpDevelop above the schemas folder). |
||||
|
||||
|
||||
XmlEditor addin |
||||
--------------- |
||||
|
||||
The binary and its addin file will exist in AddIns/AddIns/DisplayBindings/XmlEditor |
||||
|
||||
Folding |
||||
------- |
||||
|
||||
The standard way in SharpDevelop that folds are added is via the parser. The SharpDevelop has a parser thread which checks if the current view's text has changed, then looks for a parser that can handle that particular filename. This parser then parses the contents and the IParseInformation is sent to the view's IParseInformationListener.ParseInformationUpdated method. This method then usually uses the parse info to update the foldings. |
||||
|
||||
Now, the SharpDevelop parsers are programming language orientated, so a lot of the properties and objects are not relevant to parsed xml, so do we create a parser just to update the folds? The fold updating still needs to be done on a background thread, because folds aren't massively important, so creating our own extra thread is out of the question. We could trigger a fold update on every key press, but again this is overkill and will be probably be slow. |
||||
|
||||
Enabling searching in the xml editor |
||||
------------------------------------ |
||||
|
||||
The view class needs to implement the ITextEditorControlProvider otherwise the search menu options are disabled. |
||||
|
||||
@ -0,0 +1,50 @@
@@ -0,0 +1,50 @@
|
||||
INSTALLATION: |
||||
------------- |
||||
|
||||
Using Binaries |
||||
-------------- |
||||
|
||||
Assuming SharpDevelop is installed in the folder "C:/Program Files/SharpDevelop" |
||||
|
||||
Copy the contents of the "bin" folder to "C:/Program Files/SharpDevelop/AddIns/AddIns/DisplayBindings/XmlEditor". |
||||
|
||||
The binaries should work with SharpDevelop v1.0.3.1768. |
||||
|
||||
|
||||
Building source |
||||
--------------- |
||||
|
||||
Copy the contents of the XmlEditor folder to "src/AddIns/DisplayBindings/XmlEditor". |
||||
|
||||
Load the "XmlEditor.cmbx" combine and build the project OR run the "XmlEditor.build" file with NAnt 0.84. |
||||
|
||||
|
||||
Configuring Schema Auto-completion |
||||
---------------------------------- |
||||
|
||||
Go to Tools->Options->Text Editor->Xml Schemas. Use the Add button to add your .xsds to SharpDevelop. |
||||
|
||||
|
||||
|
||||
Done: |
||||
----- |
||||
|
||||
Properties taken from SharpDevelop. |
||||
Handle property changes whilst editor is open. |
||||
Validate xml menu only available for the xml editor. |
||||
Validation against schema. Right click and menu option. |
||||
User added xsds. |
||||
System xsds. |
||||
Check that we can still "jump to" NAnt errors in .build files. |
||||
Test getting element completion data for the root element of a document. |
||||
Code completion window size. Long namespace URIs do not fit in the window. Duplicated |
||||
the CodeCompletionWindow class. The item width calculation should really be in |
||||
the CodeCompletionListView. |
||||
Custom code completion window. Only autocomplete when the tab or return key |
||||
is pressed. |
||||
Validation of the xml against the schema - send output to build window and add |
||||
task list entry. |
||||
Comment folding. |
||||
Recognise special file extensions (e.g. build). Allow user to specify schema |
||||
for a file extension. This would act as a default, but could be overriden |
||||
by specifying an xmlns in the xml. |
||||
@ -1,33 +1,22 @@
@@ -1,33 +1,22 @@
|
||||
#region Using directives
|
||||
// <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.Reflection; |
||||
using System.Runtime.InteropServices; |
||||
|
||||
#endregion
|
||||
// Information about this assembly is defined by the following
|
||||
// attributes.
|
||||
//
|
||||
// change them to the information which is associated with the assembly
|
||||
// you compile.
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("XmlEditor")] |
||||
[assembly: AssemblyDescription("")] |
||||
[assembly: AssemblyDescription("SharpDevelop Xml Editor AddIn")] |
||||
[assembly: AssemblyConfiguration("")] |
||||
[assembly: AssemblyCompany("")] |
||||
[assembly: AssemblyProduct("XmlEditor")] |
||||
[assembly: AssemblyCopyright("Copyright 2009")] |
||||
[assembly: AssemblyTrademark("")] |
||||
[assembly: AssemblyCulture("")] |
||||
|
||||
// This sets the default COM visibility of types in the assembly to invisible.
|
||||
// If you need to expose a type to COM, use [ComVisible(true)] on that type.
|
||||
[assembly: ComVisible(false)] |
||||
|
||||
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("XmlEditor.Tests")] |
||||
|
||||
// The assembly version has following format :
|
||||
//
|
||||
// Major.Minor.Build.Revision
|
||||
//
|
||||
// You can specify all the values or you can use the default the Revision and
|
||||
// Build Numbers by using the '*' as shown below:
|
||||
[assembly: AssemblyVersion("1.0.*")] |
||||
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("XmlEditor.Tests")] |
||||
@ -1,28 +0,0 @@
@@ -1,28 +0,0 @@
|
||||
// <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 ICSharpCode.TextEditor;
|
||||
//using ICSharpCode.TextEditor.Actions;
|
||||
|
||||
namespace ICSharpCode.XmlEditor |
||||
{ |
||||
// /// <summary>
|
||||
// /// Command executed when the user hits Ctrl+Space
|
||||
// /// </summary>
|
||||
// public class CodeCompletionPopupCommand : AbstractEditAction
|
||||
// {
|
||||
// public override void Execute(TextArea services)
|
||||
// {
|
||||
// throw new NotImplementedException();
|
||||
//// XmlEditorControl editor = services.MotherTextEditorControl as XmlEditorControl;
|
||||
//// if (editor != null) {
|
||||
//// editor.ShowCompletionWindow();
|
||||
//// }
|
||||
// }
|
||||
// }
|
||||
} |
||||
Loading…
Reference in new issue