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
;
40 using System
.Xml
.Schema
;
45 public class XmlElement
: XmlLinkedNode
, IHasXmlChildNode
49 private XmlAttributeCollection attributes
;
50 private XmlNameEntry name
;
51 XmlLinkedNode lastLinkedChild
;
53 private bool isNotEmpty
;
55 IXmlSchemaInfo schemaInfo
;
62 protected internal XmlElement (
66 XmlDocument doc
) : this (prefix
, localName
, namespaceURI
, doc
, false)
75 bool atomizedNames
) : base (doc
)
79 prefix
= String
.Empty
;
80 if (namespaceURI
== null)
81 namespaceURI
= String
.Empty
;
83 XmlConvert
.VerifyName (localName
);
85 prefix
= doc
.NameTable
.Add (prefix
);
86 localName
= doc
.NameTable
.Add (localName
);
87 namespaceURI
= doc
.NameTable
.Add (namespaceURI
);
89 name
= doc
.NameCache
.Add (prefix
, localName
, namespaceURI
, true);
91 if(doc
.DocumentType
!= null)
93 DTDAttListDeclaration attlist
= doc
.DocumentType
.DTD
.AttListDecls
[localName
];
94 if (attlist
!= null) {
95 for (int i
= 0; i
< attlist
.Definitions
.Count
; i
++) {
96 DTDAttributeDefinition def
= attlist
[i
];
97 if (def
.DefaultValue
!= null) {
98 SetAttribute (def
.Name
, def
.DefaultValue
);
99 Attributes
[def
.Name
].SetDefault ();
110 XmlLinkedNode IHasXmlChildNode
.LastLinkedChild
{
111 get { return lastLinkedChild; }
112 set { lastLinkedChild = value; }
115 public override XmlAttributeCollection Attributes
{
117 if (attributes
== null)
118 attributes
= new XmlAttributeCollection (this);
123 public virtual bool HasAttributes
{
124 get { return attributes != null && attributes.Count > 0; }
127 public override string InnerText
{
129 return base.InnerText
;
132 // Why its behavior (of MS FCL) is different from InnerXml...?
133 if (FirstChild
!= null && FirstChild
.NextSibling
== null && FirstChild
.NodeType
== XmlNodeType
.Text
)
134 FirstChild
.Value
= value;
136 while (FirstChild
!= null)
137 this.RemoveChild (FirstChild
);
138 // creates new Text node
139 AppendChild (OwnerDocument
.CreateTextNode (value), false);
144 public override string InnerXml
{
146 return base.InnerXml
;
149 while (FirstChild
!= null)
150 this.RemoveChild (FirstChild
);
152 XmlNamespaceManager nsmgr
= this.ConstructNamespaceManager ();
153 XmlParserContext ctx
= new XmlParserContext (OwnerDocument
.NameTable
, nsmgr
,
154 OwnerDocument
.DocumentType
!= null ? OwnerDocument
.DocumentType
.DTD
: null,
155 BaseURI
, XmlLang
, XmlSpace
, null);
156 XmlTextReader xmlReader
= new XmlTextReader (value, XmlNodeType
.Element
, ctx
);
157 xmlReader
.XmlResolver
= OwnerDocument
.Resolver
;
160 XmlNode n
= OwnerDocument
.ReadNode (xmlReader
);
167 public bool IsEmpty
{
169 return !isNotEmpty
&& (FirstChild
== null);
175 while (FirstChild
!= null)
176 RemoveChild (FirstChild
);
181 public override string LocalName
{
182 get { return name.LocalName; }
185 public override string Name
{
186 get { return name.GetPrefixedName (OwnerDocument.NameCache); }
189 public override string NamespaceURI
{
190 get { return name.NS; }
193 public override XmlNode NextSibling
{
194 get { return ParentNode == null || ((IHasXmlChildNode) ParentNode).LastLinkedChild == this ? null : NextLinkedSibling; }
197 public override XmlNodeType NodeType
{
199 return XmlNodeType
.Element
;
203 internal override XPathNodeType XPathNodeType
{
205 return XPathNodeType
.Element
;
209 public override XmlDocument OwnerDocument
{
211 return base.OwnerDocument
;
215 public override string Prefix
{
216 get { return name.Prefix; }
219 throw new ArgumentException ("This node is readonly.");
222 value = string.Empty
;
224 throw new ArgumentNullException ("Prefix value is null.");
227 if ((!String
.Empty
.Equals(value))&&(!XmlChar
.IsNCName (value)))
228 throw new ArgumentException ("Specified name is not a valid NCName: " + value);
230 value = OwnerDocument
.NameTable
.Add (value);
231 name
= OwnerDocument
.NameCache
.Add (value,
232 name
.LocalName
, name
.NS
, true);
237 public override XmlNode ParentNode
{
238 get { return base.ParentNode; }
241 public override IXmlSchemaInfo SchemaInfo
{
242 get { return schemaInfo; }
243 internal set { schemaInfo = value; }
251 public override XmlNode
CloneNode (bool deep
)
253 XmlElement node
= OwnerDocument
.CreateElement (
254 name
.Prefix
, name
.LocalName
, name
.NS
, true);
256 for (int i
= 0; i
< Attributes
.Count
; i
++)
257 node
.SetAttributeNode ((XmlAttribute
)
258 Attributes
[i
].CloneNode (true));
261 for (int i
= 0; i
< ChildNodes
.Count
; i
++)
262 node
.AppendChild (ChildNodes
[i
].CloneNode (true), false);
268 public virtual string GetAttribute (string name
)
270 XmlNode attributeNode
= Attributes
.GetNamedItem (name
);
271 return attributeNode
!= null ? attributeNode
.Value
: String
.Empty
;
274 public virtual string GetAttribute (string localName
, string namespaceURI
)
276 XmlNode attributeNode
= Attributes
.GetNamedItem (localName
, namespaceURI
);
277 return attributeNode
!= null ? attributeNode
.Value
: String
.Empty
;
280 public virtual XmlAttribute
GetAttributeNode (string name
)
282 XmlNode attributeNode
= Attributes
.GetNamedItem (name
);
283 return attributeNode
!= null ? attributeNode
as XmlAttribute
: null;
286 public virtual XmlAttribute
GetAttributeNode (string localName
, string namespaceURI
)
288 XmlNode attributeNode
= Attributes
.GetNamedItem (localName
, namespaceURI
);
289 return attributeNode
!= null ? attributeNode
as XmlAttribute
: null;
292 public virtual XmlNodeList
GetElementsByTagName (string name
)
294 ArrayList nodeArrayList
= new ArrayList ();
295 this.SearchDescendantElements (name
, name
== "*", nodeArrayList
);
296 return new XmlNodeArrayList (nodeArrayList
);
299 public virtual XmlNodeList
GetElementsByTagName (string localName
, string namespaceURI
)
301 ArrayList nodeArrayList
= new ArrayList ();
302 this.SearchDescendantElements (localName
, localName
== "*", namespaceURI
, namespaceURI
== "*", nodeArrayList
);
303 return new XmlNodeArrayList (nodeArrayList
);
306 public virtual bool HasAttribute (string name
)
308 XmlNode attributeNode
= Attributes
.GetNamedItem (name
);
309 return attributeNode
!= null;
312 public virtual bool HasAttribute (string localName
, string namespaceURI
)
314 XmlNode attributeNode
= Attributes
.GetNamedItem (localName
, namespaceURI
);
315 return attributeNode
!= null;
318 public override void RemoveAll ()
320 // Remove all attributes and child nodes.
324 public virtual void RemoveAllAttributes ()
326 if (attributes
!= null)
327 attributes
.RemoveAll ();
330 public virtual void RemoveAttribute (string name
)
332 if (attributes
== null)
334 XmlAttribute attr
= Attributes
.GetNamedItem (name
) as XmlAttribute
;
336 Attributes
.Remove(attr
);
339 public virtual void RemoveAttribute (string localName
, string namespaceURI
)
341 if (attributes
== null)
344 XmlAttribute attr
= attributes
.GetNamedItem(localName
, namespaceURI
) as XmlAttribute
;
346 Attributes
.Remove(attr
);
349 public virtual XmlNode
RemoveAttributeAt (int i
)
351 if (attributes
== null || attributes
.Count
<= i
)
353 return Attributes
.RemoveAt (i
);
356 public virtual XmlAttribute
RemoveAttributeNode (XmlAttribute oldAttr
)
358 if (attributes
== null)
360 return Attributes
.Remove (oldAttr
);
363 public virtual XmlAttribute
RemoveAttributeNode (string localName
, string namespaceURI
)
365 if (attributes
== null)
367 return Attributes
.Remove (attributes
[localName
, namespaceURI
]);
370 public virtual void SetAttribute (string name
, string value)
372 XmlAttribute attr
= Attributes
[name
];
374 attr
= OwnerDocument
.CreateAttribute (name
);
376 Attributes
.SetNamedItem (attr
);
382 public virtual string SetAttribute (string localName
, string namespaceURI
, string value)
384 XmlAttribute attr
= Attributes
[localName
, namespaceURI
];
386 attr
= OwnerDocument
.CreateAttribute (localName
, namespaceURI
);
388 Attributes
.SetNamedItem (attr
);
395 public virtual XmlAttribute
SetAttributeNode (XmlAttribute newAttr
)
397 if (newAttr
.OwnerElement
!= null)
398 throw new InvalidOperationException (
399 "Specified attribute is already an attribute of another element.");
401 XmlAttribute ret
= Attributes
.SetNamedItem (newAttr
) as XmlAttribute
;
402 return ret
== newAttr
? null : ret
;
405 public virtual XmlAttribute
SetAttributeNode (string localName
, string namespaceURI
)
407 // Note that this constraint is only for this method.
408 // SetAttribute() allows prefixed name.
409 XmlConvert
.VerifyNCName (localName
);
411 return Attributes
.Append (OwnerDocument
.CreateAttribute (String
.Empty
, localName
, namespaceURI
, false, true));
414 public override void WriteContentTo (XmlWriter w
)
416 for (XmlNode n
= FirstChild
; n
!= null; n
= n
.NextSibling
)
420 public override void WriteTo (XmlWriter w
)
422 w
.WriteStartElement (
423 name
.NS
== null || name
.NS
.Length
== 0 ? String
.Empty
: name
.Prefix
,
428 for (int i
= 0; i
< Attributes
.Count
; i
++)
429 Attributes
[i
].WriteTo (w
);
434 w
.WriteEndElement ();
436 w
.WriteFullEndElement ();