1 //------------------------------------------------------------------------------
2 // <copyright file="XmlAttribute.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // <owner current="true" primary="true">Microsoft</owner>
6 //------------------------------------------------------------------------------
10 using System.Xml.Schema;
11 using System.Xml.XPath;
12 using System.Diagnostics;
14 // Represents an attribute of the XMLElement object. Valid and default
15 // values for the attribute are defined in a DTD or schema.
16 public class XmlAttribute : XmlNode {
18 XmlLinkedNode lastChild;
20 internal XmlAttribute( XmlName name, XmlDocument doc ): base( doc ) {
21 Debug.Assert(name!=null);
22 Debug.Assert(doc!=null);
23 this.parentNode = null;
24 if ( !doc.IsLoading ) {
25 XmlDocument.CheckName( name.Prefix );
26 XmlDocument.CheckName( name.LocalName );
28 if (name.LocalName.Length == 0)
29 throw new ArgumentException(Res.GetString(Res.Xdom_Attr_Name));
33 internal int LocalNameHash {
34 get { return name.HashCode; }
37 protected internal XmlAttribute( string prefix, string localName, string namespaceURI, XmlDocument doc )
38 : this(doc.AddAttrXmlName(prefix, localName, namespaceURI, null), doc) {
41 internal XmlName XmlName {
46 // Creates a duplicate of this node.
47 public override XmlNode CloneNode(bool deep) {
48 // CloneNode for attributes is deep irrespective of parameter 'deep' value
49 Debug.Assert( OwnerDocument != null );
50 XmlDocument doc = OwnerDocument;
51 XmlAttribute attr = doc.CreateAttribute( Prefix, LocalName, NamespaceURI );
52 attr.CopyChildren( doc, this, true );
56 // Gets the parent of this node (for nodes that can have parents).
57 public override XmlNode ParentNode {
61 // Gets the name of the node.
62 public override String Name {
63 get { return name.Name;}
66 // Gets the name of the node without the namespace prefix.
67 public override String LocalName {
68 get { return name.LocalName;}
71 // Gets the namespace URI of this node.
72 public override String NamespaceURI {
73 get { return name.NamespaceURI;}
76 // Gets or sets the namespace prefix of this node.
77 public override String Prefix {
78 get { return name.Prefix;}
79 set { name = name.OwnerDocument.AddAttrXmlName( value, LocalName, NamespaceURI, SchemaInfo ); }
82 // Gets the type of the current node.
83 public override XmlNodeType NodeType {
84 get { return XmlNodeType.Attribute;}
87 // Gets the XmlDocument that contains this node.
88 public override XmlDocument OwnerDocument {
90 return name.OwnerDocument;
94 // Gets or sets the value of the node.
95 public override String Value {
96 get { return InnerText; }
97 set { InnerText = value; } //use InnerText which has perf optimization
100 public override IXmlSchemaInfo SchemaInfo {
106 public override String InnerText {
108 if (PrepareOwnerElementInElementIdAttrMap()) {
109 string innerText = base.InnerText;
110 base.InnerText = value;
111 ResetOwnerElementInElementIdAttrMap(innerText);
114 base.InnerText = value;
119 internal bool PrepareOwnerElementInElementIdAttrMap() {
120 XmlDocument ownerDocument = OwnerDocument;
121 if (ownerDocument.DtdSchemaInfo != null) { // DTD exists
122 XmlElement ownerElement = OwnerElement;
123 if (ownerElement != null) {
124 return ownerElement.Attributes.PrepareParentInElementIdAttrMap(Prefix, LocalName);
130 internal void ResetOwnerElementInElementIdAttrMap(string oldInnerText) {
131 XmlElement ownerElement = OwnerElement;
132 if (ownerElement != null) {
133 ownerElement.Attributes.ResetParentInElementIdAttrMap(oldInnerText, InnerText);
137 internal override bool IsContainer {
141 //the function is provided only at Load time to speed up Load process
142 internal override XmlNode AppendChildForLoad(XmlNode newChild, XmlDocument doc) {
143 XmlNodeChangedEventArgs args = doc.GetInsertEventArgsForLoad( newChild, this );
146 doc.BeforeEvent( args );
148 XmlLinkedNode newNode = (XmlLinkedNode)newChild;
150 if (lastChild == null) { // if LastNode == null
151 newNode.next = newNode;
153 newNode.SetParentForLoad(this);
156 XmlLinkedNode refNode = lastChild; // refNode = LastNode;
157 newNode.next = refNode.next;
158 refNode.next = newNode;
159 lastChild = newNode; // LastNode = newNode;
162 NestTextNodes(refNode, newNode);
165 newNode.SetParentForLoad(this);
170 doc.AfterEvent( args );
175 internal override XmlLinkedNode LastNode {
176 get { return lastChild;}
177 set { lastChild = value;}
180 internal override bool IsValidChildType( XmlNodeType type ) {
181 return(type == XmlNodeType.Text) || (type == XmlNodeType.EntityReference);
184 // Gets a value indicating whether the value was explicitly set.
185 public virtual bool Specified {
189 public override XmlNode InsertBefore(XmlNode newChild, XmlNode refChild) {
191 if (PrepareOwnerElementInElementIdAttrMap()) {
192 string innerText = InnerText;
193 node = base.InsertBefore(newChild, refChild);
194 ResetOwnerElementInElementIdAttrMap(innerText);
197 node = base.InsertBefore(newChild, refChild);
202 public override XmlNode InsertAfter(XmlNode newChild, XmlNode refChild) {
204 if (PrepareOwnerElementInElementIdAttrMap()) {
205 string innerText = InnerText;
206 node = base.InsertAfter(newChild, refChild);
207 ResetOwnerElementInElementIdAttrMap(innerText);
210 node = base.InsertAfter(newChild, refChild);
215 public override XmlNode ReplaceChild(XmlNode newChild, XmlNode oldChild) {
217 if (PrepareOwnerElementInElementIdAttrMap()) {
218 string innerText = InnerText;
219 node = base.ReplaceChild(newChild, oldChild);
220 ResetOwnerElementInElementIdAttrMap(innerText);
223 node = base.ReplaceChild(newChild, oldChild);
228 public override XmlNode RemoveChild(XmlNode oldChild) {
230 if (PrepareOwnerElementInElementIdAttrMap()) {
231 string innerText = InnerText;
232 node = base.RemoveChild(oldChild);
233 ResetOwnerElementInElementIdAttrMap(innerText);
236 node = base.RemoveChild(oldChild);
241 public override XmlNode PrependChild(XmlNode newChild) {
243 if (PrepareOwnerElementInElementIdAttrMap()) {
244 string innerText = InnerText;
245 node = base.PrependChild(newChild);
246 ResetOwnerElementInElementIdAttrMap(innerText);
249 node = base.PrependChild(newChild);
254 public override XmlNode AppendChild(XmlNode newChild) {
256 if (PrepareOwnerElementInElementIdAttrMap()) {
257 string innerText = InnerText;
258 node = base.AppendChild(newChild);
259 ResetOwnerElementInElementIdAttrMap(innerText);
262 node = base.AppendChild(newChild);
269 // Gets the XmlElement node that contains this attribute.
270 public virtual XmlElement OwnerElement {
272 return parentNode as XmlElement;
276 // Gets or sets the markup representing just the children of this node.
277 public override string InnerXml {
280 XmlLoader loader = new XmlLoader();
281 loader.LoadInnerXmlAttribute( this, value );
285 // Saves the node to the specified XmlWriter.
286 public override void WriteTo(XmlWriter w) {
287 w.WriteStartAttribute( Prefix, LocalName, NamespaceURI );
289 w.WriteEndAttribute();
292 // Saves all the children of the node to the specified XmlWriter.
293 public override void WriteContentTo(XmlWriter w) {
294 for (XmlNode node = FirstChild; node != null; node = node.NextSibling) {
299 public override String BaseURI {
301 if ( OwnerElement != null )
302 return OwnerElement.BaseURI;
307 internal override void SetParent(XmlNode node) {
308 this.parentNode = node;
311 internal override XmlSpace XmlSpace {
313 if ( OwnerElement != null )
314 return OwnerElement.XmlSpace;
315 return XmlSpace.None;
319 internal override String XmlLang {
321 if ( OwnerElement != null )
322 return OwnerElement.XmlLang;
326 internal override XPathNodeType XPNodeType {
329 return XPathNodeType.Namespace;
331 return XPathNodeType.Attribute;
335 internal override string XPLocalName {
337 if (name.Prefix.Length == 0 && name.LocalName == "xmlns") return string.Empty;
338 return name.LocalName;
342 internal bool IsNamespace {
344 return Ref.Equal(name.NamespaceURI, name.OwnerDocument.strReservedXmlns);