public XmlTreeNode GetTreeNode(XmlDocument owner, XmlTreeNode target, XmlTreeView view) { XmlTreeNode node = view.CreateTreeNode(); if (this.img == -1 && this.xml != null){ Regex regex = new Regex(@"[:_.\w]+\s*=\s*(""[^""]*"")|('[^']*')\s*"); Match m = regex.Match(xml); string trimmed = xml.Trim(); if (m.Success && m.Index == 0 && m.Length == xml.Length) { nodeType = (int)XmlNodeType.Attribute; img = (int)NodeImage.Attribute - 1; } else if (trimmed.StartsWith("<?")) { nodeType = (int)XmlNodeType.ProcessingInstruction; img = (int)NodeImage.PI - 1; } else if (trimmed.StartsWith("<!--")) { nodeType = (int)XmlNodeType.Comment; img = (int)NodeImage.Comment - 1; } else if (trimmed.StartsWith("<![CDATA[")) { nodeType = (int)XmlNodeType.CDATA; img = (int)NodeImage.CData - 1; } else if (trimmed.StartsWith("<")) { nodeType = (int)XmlNodeType.Element; img = (int)NodeImage.Element - 1; } else { nodeType = (int)XmlNodeType.Text; img = (int)NodeImage.Text - 1; } } XmlNode xn = null; XmlNode context = (target != null) ? target.Node : owner; if (this.nodeType == (int)XmlNodeType.Attribute) { int i = this.xml.IndexOf('='); if (i > 0) { string name = this.xml.Substring(0, i).Trim(); XmlName qname = XmlHelpers.ParseName(context, name, XmlNodeType.Attribute); xn = owner.CreateAttribute(qname.Prefix, qname.LocalName, qname.NamespaceUri); string s = this.xml.Substring(i + 1).Trim(); if (s.Length > 2) { char quote = s[0]; s = s.Substring(1, s.Length - 2); // strip off quotes // un-escape quotes in the value. xn.Value = s.Replace(quote == '\'' ? "'" : """, quote.ToString()); } } } else { XmlNamespaceManager nsmgr = XmlHelpers.GetNamespaceScope(context); XmlParserContext pcontext = new XmlParserContext(owner.NameTable, nsmgr, null, XmlSpace.None); XmlTextReader r = null; if (this.xml != null) { r = new XmlTextReader(this.xml, XmlNodeType.Element, pcontext); } else { r = new XmlTextReader(this.stm, XmlNodeType.Element, pcontext); } r.WhitespaceHandling = WhitespaceHandling.Significant; // TODO: add multi-select support, so we can insert multiple nodes also. // And find valid nodes (for example, don't attempt to insert Xml declaration // if target node is not at the top of the document, etc). // For now we just favor XML elements over other node types. ArrayList list = new ArrayList(); while (true){ XmlNode rn = owner.ReadNode(r); if (rn == null) break; if (rn is XmlElement){ xn = rn; NormalizeNamespaces((XmlElement)rn, nsmgr); } list.Add(rn); } if (xn == null && list.Count>0) xn = list[0] as XmlNode; } node.Node = xn; if (!(xn is XmlAttribute)) { view.Invalidate(); if (xn is XmlElement){ if (node.Nodes.Count <= 1){ this.img = ((int)NodeImage.Leaf -1); } } } return node; }
/// <summary> /// Insert a new element as a sibling or child of current node. This command can create /// new XmlTreeNodes and new XmlNodes to go with it, or it can /// </summary> public InsertNode(XmlTreeView view) { this.view = view; this.newNode = view.CreateTreeNode(); this.doc = view.Model.Document; this.position = InsertPosition.Child; }
/// <summary> /// Move or copy a node from one place to another place in the tree. /// </summary> /// <param name="view">The MyTreeView that we are inserting into</param> /// <param name="source">The node that we are moving. This node may not be in the tree /// and that is ok, so it might be a node that is being cut&paste from another process /// for example</param> /// <param name="target">The existing node that establishes where in the tree we want /// to move the source node to</param> /// <param name="where">The position relative to the target node (before or after)</param> /// <param name="copy">Whether we are moving or copying the source node</param> public MoveNode(XmlTreeView view, XmlTreeNode source, XmlTreeNode target, InsertPosition where, bool copy) { XmlNode sn = source.Node; XmlNode dn = target.Node; this.copy = copy; TreeView tv = view.TreeView; XmlDocument doc = view.Model.Document; this.view = view; this.sourcePosition = source.Index; view.Model.BeginUpdate(); try { if (copy) { this.wasExpanded = source.IsExpanded; XmlTreeNode newSource = view.CreateTreeNode(); if (sn != null) { sn = sn.CloneNode(true); newSource.Node = sn; } source = newSource; } this.sourceParent = new TreeParent(tv, doc, source); this.tp = new TreeParent(tv, doc, target); // normalize destination based on source node type. // for example, if source is an attribute, then it can only be // inserted amongst attributes of another node. if (tp.IsRoot && where != InsertPosition.Child) { if (sn is XmlAttribute) throw new Exception(SR.RootLevelAttributes); if (sn is XmlText || sn is XmlCDataSection) throw new Exception(SR.RootLevelText); if (sn is XmlElement && sn.OwnerDocument.DocumentElement != null && sn.OwnerDocument.DocumentElement != sn) throw new Exception(SR.RootLevelElements); if (dn is XmlDeclaration && where == InsertPosition.Before) throw new Exception(SR.RootLevelBeforeXmlDecl); } if (where != InsertPosition.Child) { if (sn is XmlAttribute) { if (!(dn is XmlAttribute)) { if (tp.AttributeCount != 0) { // move target to valid location for attributes. target = tp.GetChild(tp.AttributeCount - 1); where = InsertPosition.After; } else { // append the attribute. where = InsertPosition.Child; target = (XmlTreeNode)target.Parent; } } } else if (dn is XmlAttribute) { if (!(sn is XmlAttribute)) { int skip = tp.AttributeCount; if (tp.Count > skip) { // Move non-attribute down to beginning of child elements. target = tp.GetChild(skip); where = InsertPosition.Before; } else { // append the node. where = InsertPosition.Child; target = (XmlTreeNode)target.Parent; } } } } this.source = source; this.target = target; this.where = where; this.tp = new TreeParent(tv, doc, target); if (where == InsertPosition.Child) { this.tp.SetParent(target); } } finally { view.Model.EndUpdate(); } }