(This is a recapitulation of <http://lists.canonical.org/pipermail/kragen-tol/1999-August/000466.html>, although that contains more implementation notes, and this contains more principles. There are a few other differences of opinion.)
I have in mind an XML editor constructed on the following principles: 1. Each keystroke should have a visible effect on the screen, and should have no effects not visible on the screen. 2. The document should be close to well-formed at all times, at least in the sense that it should have no syntactically invalid tags, unmatched tags, or mis-nested tags. 3. The effect of a keystroke should be predictable from the contents of the screen; it should not depend on any invisible state. 4. The screen should display only characters from the XML document, the cursor, and possibly a selection. 5. If, starting from an empty file, you were to type the characters of a well-formed XML document, one after the other, without making any mistakes, the result should be that XML document, or at least one semantically equivalent to it. 6. If you type one wrong printable character, you should always be able to undo your mistake by hitting the backspace key once. (I think these constraints may already be a nearly complete specification for the editing behavior of the editor; I may have gone too far and specified constraints that are impossible to meet.) Why? Well, XML contains a lot of redundancy. I wonder if you could construct an XML editor that added and removed the redundant information in as you typed, so that your document was always at least mostly well-formed XML; but at the same time, didn't get in your way to the extent to which you typed that information yourself. Autocompletion of tag and attribute names, of course, is another way to do this. The following example interactions, with the | representing the cursor, illustrate what I mean. Tags and attributes: hi | + "<" -> hi <|></> <|></> + "a" -> <a|></a> <a|></a> + space -> <a |=""></a> <a |=""></a> + "href=" -> <a href="|"></a> <a |=""></a> + ">" -> <a>|</a> <a href="|"></a> + "x.png" -> <a href="x.png|"></a> <a href="x.png|"></a> + '"' -> <a href="x.png" |=""></a> <a name="foo" |=""></a> + "/" -> <a name="foo" /|> <a name="foo" /|> + "f" -> <a name="foo" />f| <b>ex|cellent</b> + "<" -> <b>ex<|></>cellent</b> <b>ex<|></>cellent</b> + "/" -> <b>ex</|b>cellent<b></b> <b>ex</|b>cellent + "-" -> <b>ex</b>-|cellent <b>ex</|b>cellent + "b" -> <b>ex</b|>cellent <b>ex</b|>cellent + "-" -> <b>ex</b>-|cellent <b>ex</|b>cellent + ">" -> <b>ex</b>|cellent <|i>Now.</i> + "l" -> <l|i>Now.</li> <l|i>Now.</li> + ">" -> <li>|Now.</li> <i>Now.</|i> + "l" -> <li>Now.</l|i> Entities: C| + "&" -> C&|; C&|; + "oacute" -> Có|; Có|; + ";" -> Có| A &|; + space -> A & | A &|; + space -> A & | Deletion: <b>ex</|b>cellent<b></b> + backspace -> <b>ex<|></>cellent</b> <b>ex</b|>cellent<b></b> + backspace -> <b>ex<|></>cellent</b> <b>ex</b>|cellent<b></b> + backspace -> <b>ex|cellent</b> <i><b>ex</b>|cellent</i> + backspace -> <i><b></b>ex|cellent</i> <i><b>|ex</b>cellent</i> + backspace -> <i><|>ex</>cellent</i> <i><|>ex</>cellent</i> + backspace -> <i>excellent</i> <p width="90">Y|es</p> + backspace -> <p width="90">|es</p> <p width="90">|es</p> + backspace -> <p width="90|">es</p> <p width="90|">es</p> + backspace -> <p width="9|">es</p> <p width="9|">es</p> + backspace -> <p width="|">es</p> <p width="|">es</p> + backspace -> <p widt|="">es</p> <p |="">es</p> + backspace -> <p|>es</p> <p|>es</p> + backspace -> <|>es</> <|>es</> + backspace -> |es "| + backspace -> "|; "Yes&|quot; + backspace -> "Yes|" "Yes&|; + backspace -> "Yes| (other cases I haven't worked out but which I think the above six principles will clearly guide: deletion of tag name characters, attribute value characters, attribute name characters, entity characters, empty tag slash, close tag without a nearby matching open tag) To satisfy principle 3, the idea that you should be able to predict the effects of your actions from the screen contents, we need to display closing tags, even if they're far away. The nondestructive backspaces displayed above --- which merely move the cursor inside of some construct without deleting anything --- are necessary because typing a " or > might move you outside of those same constructs. To satisfy principle 6, hitting backspace must move you back inside those delimiters, returning you to the previous state. I think this is encapsulated in this heuristic: don't consider deleting something that might not be the last keystroke. One event the previously-mentioned rules don't cover is the insertion of an element outside the root element ("hodie natus est radici frater"). You could handle this by wrapping a new root element around the outside; I think this may violate principle 6, though. The examples shown all go through ill-formed states with tag names and attribute names that are zero characters long. This violates principle 2. One possible solution to this problem is to insert a tag or attribute name in the appropriate place, but highlight it --- and have the traditional MacOS rule that typing a printable character when there is highlighted text replaces the highlighted text with the character. If this UI idiom is supported in general, it's possible to highlight and try to delete all sorts of funny things: partial elements, partial tags, partial attributes. I'm not sure exactly how to handle this. (I'm able to consider not supporting this UI idiom because I don't like it that much, and I commonly use Emacs and vim, neither of which use it by default.) (existing popular XML editors: Oxygen (oxygenxml.com), XMLSpy, Stylus Studio. XMLSpy touts the following feature list for XML editing: Well-formedness checking Validation (DTD & schema-based) Intelligent Editing (DTD/Schema based entry-help) Text View with syntax-coloring Advanced context-sensitive entry-helpers Line Number Margin Text-folding Margin (i.e. click in the margin to fold/unfold) Bookmarks & Bookmark Margin Visual indentation guides (vertical dotted lines) Find & Replace with enhanced XML capabilities (include and exclude various syntactic categories) Find & Replace based on Regular Expressions Code-completion & syntax-help Pretty-printing of XML files Enhanced Grid & Table View (successive occurrences of the same element become numbered rows; differing attributes and subelements of the rows become columns) Browser View (HTML/XHTML Preview) "Authentic Document View*" (forms-based data entry into XML) Dynamic Forms for context-sensitive document editing CALS/HTML Table Support Spell-Checking OASIS Catalog Support (subset) "Text View remains the most popular editing view." <http://www.altova.com/support_freexmlspyhome.asp> )