2002-12-24 Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
[mono.git] / mcs / class / System.XML / System.Xml / XmlAttribute.cs
index afccdbdd9d66dbd1999418d5b53cc7d83745491a..167a9b18abaa60b57bf42f77ff0c7ad41b2a06ba 100644 (file)
-// -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-\r
-//\r
-// System.Xml.XmlAttribute\r
-//\r
-// Author:\r
-//   Daniel Weber (daniel-weber@austin.rr.com)\r
-//\r
-// (C) 2001 Daniel Weberusing System;\r
-\r
-namespace System.Xml\r
-{\r
-       /// <summary>\r
-       /// Summary description for XmlAttribute.\r
-       /// </summary>\r
-       public class XmlAttribute : XmlNode\r
-       {\r
-               // ============  private data structures ==============================\r
-               private  XmlNode FOwner;\r
-               private XmlNode FOwnerElement;\r
-               \r
-               string FelementName;\r
-               string FattrName;\r
-               string FattrValue;\r
-               \r
-               //==== Public Properties ====================================================\r
-\r
-\r
-\r
-               /// <summary>\r
-               /// Saves all children of the current node to the passed writer\r
-               /// </summary>\r
-               /// <param name="w"></param>\r
-               public override void WriteContentTo(XmlWriter w)\r
-               {\r
-                       // TODO - implement XmlAttribute.WriteContentsTo(XmlWriter)\r
-                       throw new NotImplementedException();\r
-               }\r
-\r
-               /// <summary>\r
-               /// Saves the current node to writer w\r
-               /// </summary>\r
-               /// <param name="w"></param>\r
-               public override void WriteTo(XmlWriter w)\r
-               {\r
-                       // TODO - implement XmlAttribute.WriteTo(XmlWriter)\r
-                       throw new NotImplementedException();\r
-               }\r
-\r
-               /// <summary>\r
-               /// Returns the local name of the attribute.  For attributes, this is the same as Name\r
-               /// </summary>\r
-               public override string LocalName \r
-               {\r
-                       get\r
-                       {\r
-                               return Name;\r
-                       }\r
-               }\r
-\r
-               /// <summary>\r
-               /// Get the XmlNode representing the owning document\r
-               /// </summary>\r
-               public override XmlDocument OwnerDocument\r
-               {\r
-                       get\r
-                       {\r
-                               if (FOwner.NodeType == XmlNodeType.Document)\r
-                                       return FOwner as XmlDocument;\r
-                               else\r
-                                       return null;\r
-                       }\r
-               }\r
-\r
-               /// <summary>\r
-               /// Retrieve the XmlElement owner of this attribute, or null if attribute not assigned\r
-               /// </summary>\r
-               public virtual XmlElement OwnerElement\r
-               {\r
-                       get\r
-                       {\r
-                               if (FOwnerElement.NodeType == XmlNodeType.Element)\r
-                                       return FOwnerElement as XmlElement;\r
-                               else\r
-                                       return null;\r
-                       }\r
-               }\r
-               /// <summary>\r
-               /// Get the qualified attribute name.  Attributes do not have an associated namespace.\r
-               /// </summary>\r
-               public override string Name \r
-               { \r
-                       get\r
-                       {\r
-                               return Name;\r
-                       }\r
-               }\r
-\r
-               //============== Public Methods =============================================\r
-               /// <summary>\r
-               /// Override.  Returns the node type.\r
-               /// </summary>\r
-               public override XmlNodeType NodeType \r
-               {\r
-                       get\r
-                       {\r
-                               return XmlNodeType.Attribute;\r
-                       }\r
-               }\r
-\r
-               /// <summary>\r
-               /// Return a clone of the node\r
-               /// </summary>\r
-               /// <param name="deep">Make copy of all children</param>\r
-               /// <returns>Cloned node</returns>\r
-               public override XmlNode CloneNode( bool deep)\r
-               {\r
-                       // TODO - implement XmlAttribute.CloneNode()\r
-                       throw new NotImplementedException();\r
-               }\r
-\r
-               // ============  Internal methods  ====================================\r
-               internal void setOwnerElement( XmlElement newOwnerElement)\r
-               {\r
-                       FOwnerElement = newOwnerElement;\r
-               }\r
-\r
-               // ============  Constructors =========================================\r
-               public XmlAttribute()\r
-               {\r
-                       //\r
-                       // TODO: Add constructor logic here\r
-                       //\r
-               }\r
-\r
-               internal XmlAttribute ( XmlNode aOwner,                         // owner document\r
-                       string elementName,                                                             // can be ""\r
-                       string attributeName,                                                   // cannot be ""\r
-                       // attType,\r
-                       // defaultDecl,\r
-                       string attValue)                                                                // attValue\r
-               {\r
-                       if (aOwner == null)\r
-                               throw new ArgumentException("Null OwnerDocument passed to XmlAttribute constructor");\r
-                       if (attributeName.Length == 0)\r
-                               throw new ArgumentException("Empty string passed to XmlAttribute constructor");\r
-\r
-                       FOwner = aOwner;\r
-                       FOwnerElement = null;\r
-                       FelementName = elementName;\r
-                       FattrName = attributeName;\r
-                       FattrValue = attValue;\r
-               }\r
-       \r
-\r
-       }\r
-}\r
+//
+// System.Xml.XmlAttribute
+//
+// Author:
+//   Jason Diamond (jason@injektilo.org)
+//
+// (C) 2002 Jason Diamond  http://injektilo.org/
+//
+
+using System;
+using System.Text;
+using System.Xml.XPath;
+
+namespace System.Xml
+{
+       public class XmlAttribute : XmlNode
+       {
+               #region Fields
+
+               private XmlLinkedNode lastChild;
+               private string localName;
+               private string namespaceURI;
+               private string prefix;
+               internal bool isDefault;
+               private XmlElement ownerElement;
+
+               #endregion
+
+               #region Constructor
+
+               [MonoTODO("need to set namespaceURI if prefix is recognized built-in ones like xmlns")]
+               protected internal XmlAttribute (
+                       string prefix, 
+                       string localName, 
+                       string namespaceURI, 
+                       XmlDocument doc) : base (doc)
+               {
+                       // What to be recognized is: xml:space, xml:lang, xml:base, and
+                       // xmlns and xmlns:* (when XmlDocument.Namespaces = true only)
+                       this.prefix = prefix;
+                       this.localName = localName;
+                       this.namespaceURI = namespaceURI;
+               }
+
+               #endregion
+
+               #region Properties
+
+               public override string BaseURI {
+                       get {
+                               return OwnerElement.BaseURI;
+                       }
+               }
+
+               public override string InnerText {
+                       get {
+                               StringBuilder builder = new StringBuilder ();
+                               AppendChildValues (this, builder);
+                               return builder.ToString ();
+                        }
+
+                       set {
+                               Value = value;
+                       }
+               }
+
+               private void AppendChildValues (XmlNode parent, StringBuilder builder)
+               {
+                       XmlNode node = parent.FirstChild;
+                       
+                       while (node != null) {
+                               builder.Append (node.Value);
+                               AppendChildValues (node, builder);
+                               node = node.NextSibling;
+                        }
+                }
+               
+               [MonoTODO ("Setter is incomplete(XmlTextReader.ReadAttribute is incomplete;No resolution for xml:lang/space")]
+               public override string InnerXml {
+                       get {
+                               // Not sure why this is an override.  Passing through for now.
+                               return base.InnerXml;
+                       }
+
+                       set {
+                               XmlNamespaceManager nsmgr = ConstructNamespaceManager ();
+                               XmlParserContext ctx = new XmlParserContext (OwnerDocument.NameTable, nsmgr, XmlLang, this.XmlSpace);
+                               XmlTextReader xtr = OwnerDocument.ReusableReader;
+                               xtr.SetReaderContext (BaseURI, ctx);
+                               xtr.SetReaderFragment (new System.IO.StringReader ("'" + value.Replace ("'", "&apos;") + "'"), XmlNodeType.Attribute);
+
+                               OwnerDocument.ReadAttributeNodeValue (xtr, this);
+                       }
+               }
+
+               public override string LocalName {
+                       get {
+                               return localName;
+                       }
+               }
+
+               public override string Name {
+                       get { 
+                               return prefix != String.Empty ? prefix + ":" + localName : localName; 
+                       }
+               }
+
+               public override string NamespaceURI {
+                       get {
+                               return namespaceURI;
+                       }
+               }
+
+               public override XmlNodeType NodeType {
+                       get {
+                               return XmlNodeType.Attribute;
+                       }
+               }
+
+               internal override XPathNodeType XPathNodeType {
+                       get {
+                               return XPathNodeType.Attribute;
+                       }
+               }
+
+               public override XmlDocument OwnerDocument {
+                       get {
+                               return base.OwnerDocument;
+                       }
+               }
+
+               public virtual XmlElement OwnerElement {
+                       get {
+                               return ownerElement;
+                       }
+               }
+
+               public override XmlNode ParentNode {
+                       get {
+                               // It always returns null (by specification).
+                               return null;
+                       }
+               }
+
+               [MonoTODO("setter incomplete (name character check, format check, wrong prefix&nsURI)")]
+               // We gotta do more in the set block here
+               // We need to do the proper tests and throw
+               // the correct Exceptions
+               //
+               // Wrong cases are: (1)check readonly, (2)check character validity,
+               // (3)check format validity, (4)this is attribute and qualifiedName != "xmlns"
+               // (5)when argument is 'xml' or 'xmlns' and namespaceURI doesn't match
+               public override string Prefix {
+                       set {
+                               if(IsReadOnly)
+                                       throw new XmlException ("This node is readonly.");
+
+                               XmlNamespaceManager nsmgr = ConstructNamespaceManager ();
+                               string nsuri = nsmgr.LookupNamespace (value);
+                               if(nsuri == null)
+                                       throw new XmlException ("Namespace URI not found for this prefix");
+
+                               prefix = value;
+                       }
+                       
+                       get {
+                               return prefix;
+                       }
+               }
+
+               [MonoTODO("There are no code which sets 'specified = true', so this logic is without checking.")]
+               public virtual bool Specified {
+                       get {
+                               return !isDefault;
+                       }
+               }
+
+               public override string Value {
+                       get {
+                               XmlNode firstChild = FirstChild;
+                               if (firstChild == null)
+                                       return String.Empty;
+                               return firstChild.Value;
+                       }
+
+                       set {
+                               XmlNode firstChild = FirstChild;
+                               if (firstChild == null)
+                                       AppendChild (OwnerDocument.CreateTextNode (value));
+                               else
+                                       firstChild.Value = value;
+                       }
+               }
+
+               internal override string XmlLang {
+                       get { return OwnerElement.XmlLang; }
+               }
+
+               internal override XmlSpace XmlSpace {
+                       get { return OwnerElement.XmlSpace; }
+               }
+
+               #endregion
+
+               #region Methods
+
+               public override XmlNode CloneNode (bool deep)
+               {
+                       XmlNode node = new XmlAttribute (prefix, localName, namespaceURI,
+                                                        OwnerDocument);
+                       if (deep) {
+                               while ((node != null) && (node.HasChildNodes)) {
+                                       AppendChild (node.NextSibling.CloneNode (true));
+                                       node = node.NextSibling;
+                               }
+                       }
+
+                       return node;
+               }
+
+               // Parent of XmlAttribute must be null
+               internal void SetOwnerElement (XmlElement el) {
+                       ownerElement = el;
+               }
+
+               public override void WriteContentTo (XmlWriter w)
+               {
+                       w.WriteString (Value);
+               }
+
+               public override void WriteTo (XmlWriter w)
+               {
+                       w.WriteAttributeString (prefix, localName, namespaceURI, Value);
+               }
+
+               #endregion
+
+               internal override XmlLinkedNode LastLinkedChild {
+                       get { return lastChild; }
+
+                       set { lastChild = value; }
+               }
+       }
+}