2 // System.Xml.XmlAttribute
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) 2003 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.
35 using System
.Xml
.XPath
;
40 public class XmlAttribute
: XmlNode
44 private string localName
;
45 private string namespaceURI
;
46 private string prefix
;
47 internal bool isDefault
;
48 private XmlElement ownerElement
;
54 protected internal XmlAttribute (
58 XmlDocument doc
) : this (prefix
, localName
, namespaceURI
, doc
, false, true)
62 internal XmlAttribute (
67 bool atomizedNames
, bool checkNamespace
) : base (doc
)
70 prefix
= String
.Empty
;
71 if (namespaceURI
== null)
72 namespaceURI
= String
.Empty
;
74 // Prefix "xml" should be also checked (http://www.w3.org/XML/xml-names-19990114-errata#NE05)
75 // but MS.NET ignores such case
77 if (prefix
== "xmlns" || (prefix
== "" && localName
== "xmlns"))
78 if (namespaceURI
!= XmlNamespaceManager
.XmlnsXmlns
)
79 throw new ArgumentException ("Invalid attribute namespace for namespace declaration.");
80 else if (prefix
== "xml" && namespaceURI
!= XmlNamespaceManager
.XmlnsXml
)
81 throw new ArgumentException ("Invalid attribute namespace for namespace declaration.");
84 // There are no means to identify the DOM is namespace-
85 // aware or not, so we can only check Name validity.
86 if (prefix
!= "" && !XmlChar
.IsName (prefix
))
87 throw new ArgumentException ("Invalid attribute prefix.");
88 else if (!XmlChar
.IsName (localName
))
89 throw new ArgumentException ("Invalid attribute local name.");
93 this.localName
= localName
;
94 this.namespaceURI
= namespaceURI
;
96 this.prefix
= doc
.NameTable
.Add (prefix
);
97 this.localName
= doc
.NameTable
.Add (localName
);
98 this.namespaceURI
= doc
.NameTable
.Add (namespaceURI
);
106 public override string BaseURI
{
107 get { return OwnerElement != null ? OwnerElement.BaseURI : String.Empty; }
110 public override string InnerText
{
112 return base.InnerText
;
120 public override string InnerXml
{
122 // Not sure why this is an override. Passing through for now.
123 return base.InnerXml
;
128 XmlNamespaceManager nsmgr
= ConstructNamespaceManager ();
129 XmlParserContext ctx
= new XmlParserContext (OwnerDocument
.NameTable
, nsmgr
,
130 OwnerDocument
.DocumentType
!= null ? OwnerDocument
.DocumentType
.DTD
: null,
131 BaseURI
, XmlLang
, XmlSpace
, null);
132 XmlTextReader xtr
= new XmlTextReader (value, XmlNodeType
.Attribute
, ctx
);
133 xtr
.XmlResolver
= OwnerDocument
.Resolver
;
135 OwnerDocument
.ReadAttributeNodeValue (xtr
, this);
139 public override string LocalName
{
145 public override string Name
{
147 return prefix
!= String
.Empty
? OwnerDocument
.NameTable
.Add (prefix
+ ":" + localName
) : localName
;
151 public override string NamespaceURI
{
157 public override XmlNodeType NodeType
{
159 return XmlNodeType
.Attribute
;
163 internal override XPathNodeType XPathNodeType
{
165 return XPathNodeType
.Attribute
;
169 public override XmlDocument OwnerDocument
{
171 return base.OwnerDocument
;
175 public virtual XmlElement OwnerElement
{
176 get { return ownerElement; }
179 public override XmlNode ParentNode
{
181 // It always returns null (by specification).
186 // We gotta do more in the set block here
187 // We need to do the proper tests and throw
188 // the correct Exceptions
190 // Wrong cases are: (1)check readonly, (2)check character validity,
191 // (3)check format validity, (4)this is attribute and qualifiedName != "xmlns"
192 public override string Prefix
{
195 throw new XmlException ("This node is readonly.");
196 if (!XmlChar
.IsNCName (value))
197 throw new ArgumentException ("Specified name is not a valid NCName: " + value);
198 if (prefix
== "xmlns" && value != "xmlns")
199 throw new ArgumentException ("Cannot bind to the reserved namespace.");
201 prefix
= OwnerDocument
.NameTable
.Add (value);
209 public virtual bool Specified
{
215 private string BuildChildValue (XmlNodeList list
)
217 string ret
= String
.Empty
;
218 for (int i
= 0; i
< list
.Count
; i
++) {
219 if (list
[i
].NodeType
== XmlNodeType
.EntityReference
)
220 ret
+= BuildChildValue (list
[i
].ChildNodes
);
222 ret
+= list
[i
].Value
;
227 public override string Value
{
228 get { return BuildChildValue (ChildNodes); }
232 throw new ArgumentException ("Attempt to modify a read-only node.");
233 XmlNode firstChild
= FirstChild
;
234 if (firstChild
== null)
235 AppendChild (OwnerDocument
.CreateTextNode (value));
236 else if (FirstChild
.NextSibling
!= null) {
238 AppendChild (OwnerDocument
.CreateTextNode (value));
241 firstChild
.Value
= value;
246 internal override string XmlLang
{
247 get { return OwnerElement != null ? OwnerElement.XmlLang : String.Empty; }
250 internal override XmlSpace XmlSpace
{
251 get { return OwnerElement != null ? OwnerElement.XmlSpace : XmlSpace.None; }
258 public override XmlNode
CloneNode (bool deep
)
260 XmlNode node
= new XmlAttribute (prefix
, localName
, namespaceURI
,
261 OwnerDocument
, true, false);
263 for (int i
= 0; i
< ChildNodes
.Count
; i
++)
264 node
.AppendChild (ChildNodes
[i
].CloneNode (deep
));
272 internal void SetDefault ()
277 // Parent of XmlAttribute must be null
278 internal void SetOwnerElement (XmlElement el
) {
282 public override void WriteContentTo (XmlWriter w
)
284 for (int i
= 0; i
< ChildNodes
.Count
; i
++)
285 ChildNodes
[i
].WriteTo (w
);
288 public override void WriteTo (XmlWriter w
)
290 w
.WriteStartAttribute (prefix
, localName
, namespaceURI
);
292 w
.WriteEndAttribute ();
295 internal DTDAttributeDefinition
GetAttributeDefinition ()
297 if (OwnerElement
== null)
300 // If it is default, then directly create new attribute.
301 DTDAttListDeclaration attList
= OwnerDocument
.DocumentType
!= null ? OwnerDocument
.DocumentType
.DTD
.AttListDecls
[OwnerElement
.Name
] : null;
302 return attList
!= null ? attList
[Name
] : null;