2 // System.Xml.XmlElement
5 // Jason Diamond (jason@injektilo.org)
6 // Atsushi Enomoto (ginga@kit.hi-ho.ne.jp)
8 // (C) 2002 Jason Diamond http://injektilo.org/
9 // (C) 2002 Atsushi Enomoto
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using System.Collections;
35 using System.Xml.XPath;
39 using System.Xml.Schema;
43 public class XmlElement : XmlLinkedNode, IHasXmlChildNode
47 private XmlAttributeCollection attributes;
48 private XmlNameEntry name;
49 XmlLinkedNode lastLinkedChild;
51 private bool isNotEmpty;
52 IXmlSchemaInfo schemaInfo;
58 protected internal XmlElement (
62 XmlDocument doc) : this (prefix, localName, namespaceURI, doc, false)
71 bool atomizedNames) : base (doc)
75 prefix = String.Empty;
76 if (namespaceURI == null)
77 namespaceURI = String.Empty;
79 XmlConvert.VerifyName (localName);
81 prefix = doc.NameTable.Add (prefix);
82 localName = doc.NameTable.Add (localName);
83 namespaceURI = doc.NameTable.Add (namespaceURI);
85 name = doc.NameCache.Add (prefix, localName, namespaceURI, true);
87 if(doc.DocumentType != null)
89 DTDAttListDeclaration attlist = doc.DocumentType.DTD.AttListDecls [localName];
90 if (attlist != null) {
91 for (int i = 0; i < attlist.Definitions.Count; i++) {
92 DTDAttributeDefinition def = attlist [i];
93 if (def.DefaultValue != null) {
94 SetAttribute (def.Name, def.DefaultValue);
95 Attributes [def.Name].SetDefault ();
106 XmlLinkedNode IHasXmlChildNode.LastLinkedChild {
107 get { return lastLinkedChild; }
108 set { lastLinkedChild = value; }
111 public override XmlAttributeCollection Attributes {
113 if (attributes == null)
114 attributes = new XmlAttributeCollection (this);
119 public virtual bool HasAttributes {
120 get { return attributes != null && attributes.Count > 0; }
123 public override string InnerText {
125 return base.InnerText;
128 // Why its behavior (of MS FCL) is different from InnerXml...?
129 if (FirstChild != null && FirstChild.NextSibling == null && FirstChild.NodeType == XmlNodeType.Text)
130 FirstChild.Value = value;
132 while (FirstChild != null)
133 this.RemoveChild (FirstChild);
134 // creates new Text node
135 AppendChild (OwnerDocument.CreateTextNode (value), false);
140 public override string InnerXml {
142 return base.InnerXml;
145 while (FirstChild != null)
146 this.RemoveChild (FirstChild);
148 XmlNamespaceManager nsmgr = this.ConstructNamespaceManager ();
149 XmlParserContext ctx = new XmlParserContext (OwnerDocument.NameTable, nsmgr,
150 OwnerDocument.DocumentType != null ? OwnerDocument.DocumentType.DTD : null,
151 BaseURI, XmlLang, XmlSpace, null);
152 XmlTextReader xmlReader = new XmlTextReader (value, XmlNodeType.Element, ctx);
153 xmlReader.XmlResolver = OwnerDocument.Resolver;
156 XmlNode n = OwnerDocument.ReadNode (xmlReader);
163 public bool IsEmpty {
165 return !isNotEmpty && (FirstChild == null);
171 while (FirstChild != null)
172 RemoveChild (FirstChild);
177 public override string LocalName {
178 get { return name.LocalName; }
181 public override string Name {
182 get { return name.GetPrefixedName (OwnerDocument.NameCache); }
185 public override string NamespaceURI {
186 get { return name.NS; }
189 public override XmlNode NextSibling {
190 get { return ParentNode == null || ((IHasXmlChildNode) ParentNode).LastLinkedChild == this ? null : NextLinkedSibling; }
193 public override XmlNodeType NodeType {
195 return XmlNodeType.Element;
199 internal override XPathNodeType XPathNodeType {
201 return XPathNodeType.Element;
205 public override XmlDocument OwnerDocument {
207 return base.OwnerDocument;
211 public override string Prefix {
212 get { return name.Prefix; }
215 throw new ArgumentException ("This node is readonly.");
217 value = string.Empty;
219 if ((!String.Empty.Equals(value))&&(!XmlChar.IsNCName (value)))
220 throw new ArgumentException ("Specified name is not a valid NCName: " + value);
222 value = OwnerDocument.NameTable.Add (value);
223 name = OwnerDocument.NameCache.Add (value,
224 name.LocalName, name.NS, true);
228 public override XmlNode ParentNode {
229 get { return base.ParentNode; }
232 public override IXmlSchemaInfo SchemaInfo {
233 get { return schemaInfo; }
234 internal set { schemaInfo = value; }
241 public override XmlNode CloneNode (bool deep)
243 XmlElement node = OwnerDocument.CreateElement (
244 name.Prefix, name.LocalName, name.NS, true);
246 for (int i = 0; i < Attributes.Count; i++)
247 node.SetAttributeNode ((XmlAttribute)
248 Attributes [i].CloneNode (true));
251 for (int i = 0; i < ChildNodes.Count; i++)
252 node.AppendChild (ChildNodes [i].CloneNode (true), false);
258 public virtual string GetAttribute (string name)
260 XmlNode attributeNode = Attributes.GetNamedItem (name);
261 return attributeNode != null ? attributeNode.Value : String.Empty;
264 public virtual string GetAttribute (string localName, string namespaceURI)
266 XmlNode attributeNode = Attributes.GetNamedItem (localName, namespaceURI);
267 return attributeNode != null ? attributeNode.Value : String.Empty;
270 public virtual XmlAttribute GetAttributeNode (string name)
272 XmlNode attributeNode = Attributes.GetNamedItem (name);
273 return attributeNode != null ? attributeNode as XmlAttribute : null;
276 public virtual XmlAttribute GetAttributeNode (string localName, string namespaceURI)
278 XmlNode attributeNode = Attributes.GetNamedItem (localName, namespaceURI);
279 return attributeNode != null ? attributeNode as XmlAttribute : null;
282 public virtual XmlNodeList GetElementsByTagName (string name)
284 ArrayList nodeArrayList = new ArrayList ();
285 this.SearchDescendantElements (name, name == "*", nodeArrayList);
286 return new XmlNodeArrayList (nodeArrayList);
289 public virtual XmlNodeList GetElementsByTagName (string localName, string namespaceURI)
291 ArrayList nodeArrayList = new ArrayList ();
292 this.SearchDescendantElements (localName, localName == "*", namespaceURI, namespaceURI == "*", nodeArrayList);
293 return new XmlNodeArrayList (nodeArrayList);
296 public virtual bool HasAttribute (string name)
298 XmlNode attributeNode = Attributes.GetNamedItem (name);
299 return attributeNode != null;
302 public virtual bool HasAttribute (string localName, string namespaceURI)
304 XmlNode attributeNode = Attributes.GetNamedItem (localName, namespaceURI);
305 return attributeNode != null;
308 public override void RemoveAll ()
310 // Remove all attributes and child nodes.
314 public virtual void RemoveAllAttributes ()
316 if (attributes != null)
317 attributes.RemoveAll ();
320 public virtual void RemoveAttribute (string name)
322 if (attributes == null)
324 XmlAttribute attr = Attributes.GetNamedItem (name) as XmlAttribute;
326 Attributes.Remove(attr);
329 public virtual void RemoveAttribute (string localName, string namespaceURI)
331 if (attributes == null)
334 XmlAttribute attr = attributes.GetNamedItem(localName, namespaceURI) as XmlAttribute;
336 Attributes.Remove(attr);
339 public virtual XmlNode RemoveAttributeAt (int i)
341 if (attributes == null || attributes.Count <= i)
343 return Attributes.RemoveAt (i);
346 public virtual XmlAttribute RemoveAttributeNode (XmlAttribute oldAttr)
348 if (attributes == null)
350 return Attributes.Remove (oldAttr);
353 public virtual XmlAttribute RemoveAttributeNode (string localName, string namespaceURI)
355 if (attributes == null)
357 return Attributes.Remove (attributes [localName, namespaceURI]);
360 public virtual void SetAttribute (string name, string value)
362 XmlAttribute attr = Attributes [name];
364 attr = OwnerDocument.CreateAttribute (name);
366 Attributes.SetNamedItem (attr);
372 public virtual string SetAttribute (string localName, string namespaceURI, string value)
374 XmlAttribute attr = Attributes [localName, namespaceURI];
376 attr = OwnerDocument.CreateAttribute (localName, namespaceURI);
378 Attributes.SetNamedItem (attr);
385 public virtual XmlAttribute SetAttributeNode (XmlAttribute newAttr)
387 if (newAttr.OwnerElement != null)
388 throw new InvalidOperationException (
389 "Specified attribute is already an attribute of another element.");
391 XmlAttribute ret = Attributes.SetNamedItem (newAttr) as XmlAttribute;
392 return ret == newAttr ? null : ret;
395 public virtual XmlAttribute SetAttributeNode (string localName, string namespaceURI)
397 // Note that this constraint is only for this method.
398 // SetAttribute() allows prefixed name.
399 XmlConvert.VerifyNCName (localName);
401 return Attributes.Append (OwnerDocument.CreateAttribute (String.Empty, localName, namespaceURI, false, true));
404 public override void WriteContentTo (XmlWriter w)
406 for (XmlNode n = FirstChild; n != null; n = n.NextSibling)
410 public override void WriteTo (XmlWriter w)
412 w.WriteStartElement (
413 name.NS == null || name.NS.Length == 0 ? String.Empty : name.Prefix,
418 for (int i = 0; i < Attributes.Count; i++)
419 Attributes [i].WriteTo (w);
424 w.WriteEndElement ();
426 w.WriteFullEndElement ();