The Labs \ Source Viewer \ SSCLI \ System.Xml \ XmlElement

  1. //------------------------------------------------------------------------------
  2. // <copyright file="XmlElement.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. using System;
  16. using System.Xml.Schema;
  17. using System.Xml.XPath;
  18. using System.Collections;
  19. using System.Diagnostics;
  20. using System.Globalization;
  21. namespace System.Xml
  22. {
  23.     // Represents an element.
  24.     public class XmlElement : XmlLinkedNode
  25.     {
  26.         XmlName name;
  27.         XmlAttributeCollection attributes;
  28.         XmlLinkedNode lastChild;
  29.         // == this for empty elements otherwise it is the last child
  30.         internal XmlElement(XmlName name, bool empty, XmlDocument doc) : base(doc)
  31.         {
  32.             Debug.Assert(name != null);
  33.             this.parentNode = null;
  34.             if (!doc.IsLoading) {
  35.                 XmlDocument.CheckName(name.Prefix);
  36.                 XmlDocument.CheckName(name.LocalName);
  37.             }
  38.             if (name.LocalName.Length == 0)
  39.                 throw new ArgumentException(Res.GetString(Res.Xdom_Empty_LocalName));
  40.             if (name.Prefix.Length >= 3 && (!doc.IsLoading) && String.Compare(name.Prefix, 0, "xml", 0, 3, StringComparison.OrdinalIgnoreCase) == 0)
  41.                 throw new ArgumentException(Res.GetString(Res.Xdom_Ele_Prefix));
  42.             this.name = name;
  43.             if (empty) {
  44.                 this.lastChild = this;
  45.             }
  46.         }
  47.        
  48.         protected internal XmlElement(string prefix, string localName, string namespaceURI, XmlDocument doc) : this(doc.AddXmlName(prefix, localName, namespaceURI, null), true, doc)
  49.         {
  50.         }
  51.        
  52.         internal XmlName XmlName {
  53.             get { return name; }
  54.             set { name = value; }
  55.         }
  56.        
  57.         // Creates a duplicate of this node.
  58.         public override XmlNode CloneNode(bool deep)
  59.         {
  60.             Debug.Assert(OwnerDocument != null);
  61.             XmlDocument doc = OwnerDocument;
  62.             bool OrigLoadingStatus = doc.IsLoading;
  63.             doc.IsLoading = true;
  64.             XmlElement element = doc.CreateElement(Prefix, LocalName, NamespaceURI);
  65.             doc.IsLoading = OrigLoadingStatus;
  66.             if (element.IsEmpty != this.IsEmpty)
  67.                 element.IsEmpty = this.IsEmpty;
  68.            
  69.             if (HasAttributes) {
  70.                 foreach (XmlAttribute attr in Attributes) {
  71.                     XmlAttribute newAttr = (XmlAttribute)(attr.CloneNode(true));
  72.                     if (attr is XmlUnspecifiedAttribute && attr.Specified == false)
  73.                         ((XmlUnspecifiedAttribute)newAttr).SetSpecified(false);
  74.                     element.Attributes.InternalAppendAttribute(newAttr);
  75.                 }
  76.             }
  77.             if (deep)
  78.                 element.CopyChildren(doc, this, deep);
  79.            
  80.             return element;
  81.         }
  82.        
  83.         // Gets the name of the node.
  84.         public override string Name {
  85.             get { return name.Name; }
  86.         }
  87.        
  88.         // Gets the name of the current node without the namespace prefix.
  89.         public override string LocalName {
  90.             get { return name.LocalName; }
  91.         }
  92.        
  93.         // Gets the namespace URI of this node.
  94.         public override string NamespaceURI {
  95.             get { return name.NamespaceURI; }
  96.         }
  97.        
  98.         // Gets or sets the namespace prefix of this node.
  99.         public override string Prefix {
  100.             get { return name.Prefix; }
  101.             set { name = name.OwnerDocument.AddXmlName(value, LocalName, NamespaceURI, SchemaInfo); }
  102.         }
  103.        
  104.         // Gets the type of the current node.
  105.         public override XmlNodeType NodeType {
  106.             get { return XmlNodeType.Element; }
  107.         }
  108.        
  109.         public override XmlNode ParentNode {
  110.             get { return this.parentNode; }
  111.         }
  112.        
  113.         // Gets the XmlDocument that contains this node.
  114.         public override XmlDocument OwnerDocument {
  115.             get { return name.OwnerDocument; }
  116.         }
  117.        
  118.         internal override bool IsContainer {
  119.             get { return true; }
  120.         }
  121.        
  122.         //the function is provided only at Load time to speed up Load process
  123.         internal override XmlNode AppendChildForLoad(XmlNode newChild, XmlDocument doc)
  124.         {
  125.             XmlNodeChangedEventArgs args = doc.GetInsertEventArgsForLoad(newChild, this);
  126.            
  127.             if (args != null)
  128.                 doc.BeforeEvent(args);
  129.            
  130.             XmlLinkedNode newNode = (XmlLinkedNode)newChild;
  131.            
  132.             if (lastChild == null || lastChild == this) {
  133.                 // if LastNode == null
  134.                 newNode.next = newNode;
  135.                 lastChild = newNode;
  136.                 // LastNode = newNode;
  137.                 newNode.SetParentForLoad(this);
  138.             }
  139.             else {
  140.                 XmlLinkedNode refNode = lastChild;
  141.                 // refNode = LastNode;
  142.                 newNode.next = refNode.next;
  143.                 refNode.next = newNode;
  144.                 lastChild = newNode;
  145.                 // LastNode = newNode;
  146.                 if (refNode.IsText && newNode.IsText) {
  147.                     NestTextNodes(refNode, newNode);
  148.                 }
  149.                 else {
  150.                     newNode.SetParentForLoad(this);
  151.                 }
  152.             }
  153.            
  154.             if (args != null)
  155.                 doc.AfterEvent(args);
  156.            
  157.             return newNode;
  158.         }
  159.        
  160.         // Gets or sets whether the element does not have any children.
  161.         public bool IsEmpty {
  162.             get { return lastChild == this; }
  163.            
  164.             set {
  165.                 if (value) {
  166.                     if (lastChild != this) {
  167.                         RemoveAllChildren();
  168.                         lastChild = this;
  169.                     }
  170.                 }
  171.                 else {
  172.                     if (lastChild == this) {
  173.                         lastChild = null;
  174.                     }
  175.                 }
  176.                
  177.             }
  178.         }
  179.        
  180.         internal override XmlLinkedNode LastNode {
  181.             get { return lastChild == this ? null : lastChild; }
  182.            
  183.             set { lastChild = value; }
  184.         }
  185.        
  186.         internal override bool IsValidChildType(XmlNodeType type)
  187.         {
  188.             switch (type) {
  189.                 case XmlNodeType.Element:
  190.                 case XmlNodeType.Text:
  191.                 case XmlNodeType.EntityReference:
  192.                 case XmlNodeType.Comment:
  193.                 case XmlNodeType.Whitespace:
  194.                 case XmlNodeType.SignificantWhitespace:
  195.                 case XmlNodeType.ProcessingInstruction:
  196.                 case XmlNodeType.CDATA:
  197.                     return true;
  198.                 default:
  199.                    
  200.                     return false;
  201.             }
  202.         }
  203.        
  204.        
  205.         // Gets a XmlAttributeCollection containing the list of attributes for this node.
  206.         public override XmlAttributeCollection Attributes {
  207.             get {
  208.                 if (attributes == null) {
  209.                     lock (OwnerDocument.objLock) {
  210.                         if (attributes == null) {
  211.                             attributes = new XmlAttributeCollection(this);
  212.                         }
  213.                     }
  214.                 }
  215.                
  216.                 return attributes;
  217.             }
  218.         }
  219.        
  220.         // Gets a value indicating whether the current node
  221.         // has any attributes.
  222.         public virtual bool HasAttributes {
  223.             get {
  224.                 if (this.attributes == null)
  225.                     return false;
  226.                 else
  227.                     return this.attributes.Count > 0;
  228.             }
  229.         }
  230.        
  231.         // Returns the value for the attribute with the specified name.
  232.         public virtual string GetAttribute(string name)
  233.         {
  234.             XmlAttribute attr = GetAttributeNode(name);
  235.             if (attr != null)
  236.                 return attr.Value;
  237.             return String.Empty;
  238.         }
  239.        
  240.         // Sets the value of the attribute
  241.         // with the specified name.
  242.         public virtual void SetAttribute(string name, string value)
  243.         {
  244.             XmlAttribute attr = GetAttributeNode(name);
  245.             if (attr == null) {
  246.                 attr = OwnerDocument.CreateAttribute(name);
  247.                 attr.Value = value;
  248.                 Attributes.InternalAppendAttribute(attr);
  249.             }
  250.             else {
  251.                 attr.Value = value;
  252.             }
  253.         }
  254.        
  255.         // Removes an attribute by name.
  256.         public virtual void RemoveAttribute(string name)
  257.         {
  258.             if (HasAttributes)
  259.                 Attributes.RemoveNamedItem(name);
  260.         }
  261.        
  262.         // Returns the XmlAttribute with the specified name.
  263.         public virtual XmlAttribute GetAttributeNode(string name)
  264.         {
  265.             if (HasAttributes)
  266.                 return Attributes[name];
  267.             return null;
  268.         }
  269.        
  270.         // Adds the specified XmlAttribute.
  271.         public virtual XmlAttribute SetAttributeNode(XmlAttribute newAttr)
  272.         {
  273.             if (newAttr.OwnerElement != null)
  274.                 throw new InvalidOperationException(Res.GetString(Res.Xdom_Attr_InUse));
  275.             return (XmlAttribute)Attributes.SetNamedItem(newAttr);
  276.         }
  277.        
  278.         // Removes the specified XmlAttribute.
  279.         public virtual XmlAttribute RemoveAttributeNode(XmlAttribute oldAttr)
  280.         {
  281.             if (HasAttributes)
  282.                 return (XmlAttribute)Attributes.Remove(oldAttr);
  283.             return null;
  284.         }
  285.        
  286.         // Returns a XmlNodeList containing
  287.         // a list of all descendant elements that match the specified name.
  288.         public virtual XmlNodeList GetElementsByTagName(string name)
  289.         {
  290.             return new XmlElementList(this, name);
  291.         }
  292.        
  293.         //
  294.         // DOM Level 2
  295.         //
  296.        
  297.         // Returns the value for the attribute with the specified LocalName and NamespaceURI.
  298.         public virtual string GetAttribute(string localName, string namespaceURI)
  299.         {
  300.             XmlAttribute attr = GetAttributeNode(localName, namespaceURI);
  301.             if (attr != null)
  302.                 return attr.Value;
  303.             return String.Empty;
  304.         }
  305.        
  306.         // Sets the value of the attribute with the specified name
  307.         // and namespace.
  308.         public virtual string SetAttribute(string localName, string namespaceURI, string value)
  309.         {
  310.             XmlAttribute attr = GetAttributeNode(localName, namespaceURI);
  311.             if (attr == null) {
  312.                 attr = OwnerDocument.CreateAttribute(string.Empty, localName, namespaceURI);
  313.                 attr.Value = value;
  314.                 Attributes.InternalAppendAttribute(attr);
  315.             }
  316.             else {
  317.                 attr.Value = value;
  318.             }
  319.            
  320.             return value;
  321.         }
  322.        
  323.         // Removes an attribute specified by LocalName and NamespaceURI.
  324.         public virtual void RemoveAttribute(string localName, string namespaceURI)
  325.         {
  326.             //Debug.Assert(namespaceURI != null);
  327.             RemoveAttributeNode(localName, namespaceURI);
  328.         }
  329.        
  330.         // Returns the XmlAttribute with the specified LocalName and NamespaceURI.
  331.         public virtual XmlAttribute GetAttributeNode(string localName, string namespaceURI)
  332.         {
  333.             //Debug.Assert(namespaceURI != null);
  334.             if (HasAttributes)
  335.                 return Attributes[localName, namespaceURI];
  336.             return null;
  337.         }
  338.        
  339.         // Adds the specified XmlAttribute.
  340.         public virtual XmlAttribute SetAttributeNode(string localName, string namespaceURI)
  341.         {
  342.             XmlAttribute attr = GetAttributeNode(localName, namespaceURI);
  343.             if (attr == null) {
  344.                 attr = OwnerDocument.CreateAttribute(string.Empty, localName, namespaceURI);
  345.                 Attributes.InternalAppendAttribute(attr);
  346.             }
  347.             return attr;
  348.         }
  349.        
  350.         // Removes the XmlAttribute specified by LocalName and NamespaceURI.
  351.         public virtual XmlAttribute RemoveAttributeNode(string localName, string namespaceURI)
  352.         {
  353.             //Debug.Assert(namespaceURI != null);
  354.             if (HasAttributes) {
  355.                 XmlAttribute attr = GetAttributeNode(localName, namespaceURI);
  356.                 Attributes.Remove(attr);
  357.                 return attr;
  358.             }
  359.             return null;
  360.         }
  361.        
  362.         // Returns a XmlNodeList containing
  363.         // a list of all descendant elements that match the specified name.
  364.         public virtual XmlNodeList GetElementsByTagName(string localName, string namespaceURI)
  365.         {
  366.             //Debug.Assert(namespaceURI != null);
  367.             return new XmlElementList(this, localName, namespaceURI);
  368.         }
  369.        
  370.         // Determines whether the current node has the specified attribute.
  371.         public virtual bool HasAttribute(string name)
  372.         {
  373.             return GetAttributeNode(name) != null;
  374.         }
  375.        
  376.         // Determines whether the current node has the specified
  377.         // attribute from the specified namespace.
  378.         public virtual bool HasAttribute(string localName, string namespaceURI)
  379.         {
  380.             return GetAttributeNode(localName, namespaceURI) != null;
  381.         }
  382.        
  383.         // Saves the current node to the specified XmlWriter.
  384.         public override void WriteTo(XmlWriter w)
  385.         {
  386.            
  387.             w.WriteStartElement(Prefix, LocalName, NamespaceURI);
  388.            
  389.             if (HasAttributes) {
  390.                 XmlAttributeCollection attrs = Attributes;
  391.                 for (int i = 0; i < attrs.Count; i += 1) {
  392.                     XmlAttribute attr = attrs[i];
  393.                     attr.WriteTo(w);
  394.                 }
  395.             }
  396.            
  397.             if (IsEmpty) {
  398.                 w.WriteEndElement();
  399.             }
  400.             else {
  401.                 WriteContentTo(w);
  402.                 w.WriteFullEndElement();
  403.             }
  404.         }
  405.        
  406.         // Saves all the children of the node to the specified XmlWriter.
  407.         public override void WriteContentTo(XmlWriter w)
  408.         {
  409.             for (XmlNode node = FirstChild; node != null; node = node.NextSibling) {
  410.                 node.WriteTo(w);
  411.             }
  412.         }
  413.        
  414.         // Removes the attribute node with the specified index from the attribute collection.
  415.         public virtual XmlNode RemoveAttributeAt(int i)
  416.         {
  417.             if (HasAttributes)
  418.                 return attributes.RemoveAt(i);
  419.             return null;
  420.         }
  421.        
  422.         // Removes all attributes from the element.
  423.         public virtual void RemoveAllAttributes()
  424.         {
  425.             if (HasAttributes) {
  426.                 attributes.RemoveAll();
  427.             }
  428.         }
  429.        
  430.         // Removes all the children and/or attributes
  431.         // of the current node.
  432.         public override void RemoveAll()
  433.         {
  434.             //remove all the children
  435.             base.RemoveAll();
  436.             //remove all the attributes
  437.             RemoveAllAttributes();
  438.         }
  439.        
  440.         internal void RemoveAllChildren()
  441.         {
  442.             base.RemoveAll();
  443.         }
  444.        
  445.         public override IXmlSchemaInfo SchemaInfo {
  446.             get { return name; }
  447.         }
  448.        
  449.         // Gets or sets the markup representing just
  450.         // the children of this node.
  451.         public override string InnerXml {
  452.             get { return base.InnerXml; }
  453.             set {
  454.                 RemoveAllChildren();
  455.                 XmlLoader loader = new XmlLoader();
  456.                 loader.LoadInnerXmlElement(this, value);
  457.             }
  458.         }
  459.        
  460.         // Gets or sets the concatenated values of the
  461.         // node and all its children.
  462.         public override string InnerText {
  463.             get { return base.InnerText; }
  464.             set {
  465.                 XmlLinkedNode linkedNode = LastNode;
  466.                 //there is one child
  467.                 //which is text node
  468.                 // and it is the only child
  469.                 if (linkedNode != null && linkedNode.NodeType == XmlNodeType.Text && linkedNode.next == linkedNode) {
  470.                     //this branch is for perf reason, event fired when TextNode.Value is changed.
  471.                     linkedNode.Value = value;
  472.                 }
  473.                 else {
  474.                     RemoveAllChildren();
  475.                     AppendChild(OwnerDocument.CreateTextNode(value));
  476.                 }
  477.             }
  478.         }
  479.        
  480.         public override XmlNode NextSibling {
  481.             get {
  482.                 if (this.parentNode != null && this.parentNode.LastNode != this)
  483.                     return next;
  484.                 return null;
  485.             }
  486.         }
  487.        
  488.         internal override void SetParent(XmlNode node)
  489.         {
  490.             this.parentNode = node;
  491.         }
  492.        
  493.         internal override XPathNodeType XPNodeType {
  494.             get { return XPathNodeType.Element; }
  495.         }
  496.        
  497.         internal override string XPLocalName {
  498.             get { return LocalName; }
  499.         }
  500.        
  501.         internal override string GetXPAttribute(string localName, string ns)
  502.         {
  503.             if (ns == OwnerDocument.strReservedXmlns)
  504.                 return null;
  505.             XmlAttribute attr = GetAttributeNode(localName, ns);
  506.             if (attr != null)
  507.                 return attr.Value;
  508.             return string.Empty;
  509.         }
  510.     }
  511. }

Developer Fusion