536cd135cc
Former-commit-id: 5624ac747d633e885131e8349322922b6a59baaa
349 lines
12 KiB
C#
349 lines
12 KiB
C#
//------------------------------------------------------------------------------
|
|
// <copyright file="XmlAttribute.cs" company="Microsoft">
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// </copyright>
|
|
// <owner current="true" primary="true">Microsoft</owner>
|
|
//------------------------------------------------------------------------------
|
|
|
|
namespace System.Xml {
|
|
using System;
|
|
using System.Xml.Schema;
|
|
using System.Xml.XPath;
|
|
using System.Diagnostics;
|
|
|
|
// Represents an attribute of the XMLElement object. Valid and default
|
|
// values for the attribute are defined in a DTD or schema.
|
|
public class XmlAttribute : XmlNode {
|
|
XmlName name;
|
|
XmlLinkedNode lastChild;
|
|
|
|
internal XmlAttribute( XmlName name, XmlDocument doc ): base( doc ) {
|
|
Debug.Assert(name!=null);
|
|
Debug.Assert(doc!=null);
|
|
this.parentNode = null;
|
|
if ( !doc.IsLoading ) {
|
|
XmlDocument.CheckName( name.Prefix );
|
|
XmlDocument.CheckName( name.LocalName );
|
|
}
|
|
if (name.LocalName.Length == 0)
|
|
throw new ArgumentException(Res.GetString(Res.Xdom_Attr_Name));
|
|
this.name = name;
|
|
}
|
|
|
|
internal int LocalNameHash {
|
|
get { return name.HashCode; }
|
|
}
|
|
|
|
protected internal XmlAttribute( string prefix, string localName, string namespaceURI, XmlDocument doc )
|
|
: this(doc.AddAttrXmlName(prefix, localName, namespaceURI, null), doc) {
|
|
}
|
|
|
|
internal XmlName XmlName {
|
|
get { return name; }
|
|
set { name = value; }
|
|
}
|
|
|
|
// Creates a duplicate of this node.
|
|
public override XmlNode CloneNode(bool deep) {
|
|
// CloneNode for attributes is deep irrespective of parameter 'deep' value
|
|
Debug.Assert( OwnerDocument != null );
|
|
XmlDocument doc = OwnerDocument;
|
|
XmlAttribute attr = doc.CreateAttribute( Prefix, LocalName, NamespaceURI );
|
|
attr.CopyChildren( doc, this, true );
|
|
return attr;
|
|
}
|
|
|
|
// Gets the parent of this node (for nodes that can have parents).
|
|
public override XmlNode ParentNode {
|
|
get { return null;}
|
|
}
|
|
|
|
// Gets the name of the node.
|
|
public override String Name {
|
|
get { return name.Name;}
|
|
}
|
|
|
|
// Gets the name of the node without the namespace prefix.
|
|
public override String LocalName {
|
|
get { return name.LocalName;}
|
|
}
|
|
|
|
// Gets the namespace URI of this node.
|
|
public override String NamespaceURI {
|
|
get { return name.NamespaceURI;}
|
|
}
|
|
|
|
// Gets or sets the namespace prefix of this node.
|
|
public override String Prefix {
|
|
get { return name.Prefix;}
|
|
set { name = name.OwnerDocument.AddAttrXmlName( value, LocalName, NamespaceURI, SchemaInfo ); }
|
|
}
|
|
|
|
// Gets the type of the current node.
|
|
public override XmlNodeType NodeType {
|
|
get { return XmlNodeType.Attribute;}
|
|
}
|
|
|
|
// Gets the XmlDocument that contains this node.
|
|
public override XmlDocument OwnerDocument {
|
|
get {
|
|
return name.OwnerDocument;
|
|
}
|
|
}
|
|
|
|
// Gets or sets the value of the node.
|
|
public override String Value {
|
|
get { return InnerText; }
|
|
set { InnerText = value; } //use InnerText which has perf optimization
|
|
}
|
|
|
|
public override IXmlSchemaInfo SchemaInfo {
|
|
get {
|
|
return name;
|
|
}
|
|
}
|
|
|
|
public override String InnerText {
|
|
set {
|
|
if (PrepareOwnerElementInElementIdAttrMap()) {
|
|
string innerText = base.InnerText;
|
|
base.InnerText = value;
|
|
ResetOwnerElementInElementIdAttrMap(innerText);
|
|
}
|
|
else {
|
|
base.InnerText = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
internal bool PrepareOwnerElementInElementIdAttrMap() {
|
|
XmlDocument ownerDocument = OwnerDocument;
|
|
if (ownerDocument.DtdSchemaInfo != null) { // DTD exists
|
|
XmlElement ownerElement = OwnerElement;
|
|
if (ownerElement != null) {
|
|
return ownerElement.Attributes.PrepareParentInElementIdAttrMap(Prefix, LocalName);
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
internal void ResetOwnerElementInElementIdAttrMap(string oldInnerText) {
|
|
XmlElement ownerElement = OwnerElement;
|
|
if (ownerElement != null) {
|
|
ownerElement.Attributes.ResetParentInElementIdAttrMap(oldInnerText, InnerText);
|
|
}
|
|
}
|
|
|
|
internal override bool IsContainer {
|
|
get { return true;}
|
|
}
|
|
|
|
//the function is provided only at Load time to speed up Load process
|
|
internal override XmlNode AppendChildForLoad(XmlNode newChild, XmlDocument doc) {
|
|
XmlNodeChangedEventArgs args = doc.GetInsertEventArgsForLoad( newChild, this );
|
|
|
|
if (args != null)
|
|
doc.BeforeEvent( args );
|
|
|
|
XmlLinkedNode newNode = (XmlLinkedNode)newChild;
|
|
|
|
if (lastChild == null) { // if LastNode == null
|
|
newNode.next = newNode;
|
|
lastChild = newNode;
|
|
newNode.SetParentForLoad(this);
|
|
}
|
|
else {
|
|
XmlLinkedNode refNode = lastChild; // refNode = LastNode;
|
|
newNode.next = refNode.next;
|
|
refNode.next = newNode;
|
|
lastChild = newNode; // LastNode = newNode;
|
|
if (refNode.IsText
|
|
&& newNode.IsText) {
|
|
NestTextNodes(refNode, newNode);
|
|
}
|
|
else {
|
|
newNode.SetParentForLoad(this);
|
|
}
|
|
}
|
|
|
|
if (args != null)
|
|
doc.AfterEvent( args );
|
|
|
|
return newNode;
|
|
}
|
|
|
|
internal override XmlLinkedNode LastNode {
|
|
get { return lastChild;}
|
|
set { lastChild = value;}
|
|
}
|
|
|
|
internal override bool IsValidChildType( XmlNodeType type ) {
|
|
return(type == XmlNodeType.Text) || (type == XmlNodeType.EntityReference);
|
|
}
|
|
|
|
// Gets a value indicating whether the value was explicitly set.
|
|
public virtual bool Specified {
|
|
get { return true;}
|
|
}
|
|
|
|
public override XmlNode InsertBefore(XmlNode newChild, XmlNode refChild) {
|
|
XmlNode node;
|
|
if (PrepareOwnerElementInElementIdAttrMap()) {
|
|
string innerText = InnerText;
|
|
node = base.InsertBefore(newChild, refChild);
|
|
ResetOwnerElementInElementIdAttrMap(innerText);
|
|
}
|
|
else {
|
|
node = base.InsertBefore(newChild, refChild);
|
|
}
|
|
return node;
|
|
}
|
|
|
|
public override XmlNode InsertAfter(XmlNode newChild, XmlNode refChild) {
|
|
XmlNode node;
|
|
if (PrepareOwnerElementInElementIdAttrMap()) {
|
|
string innerText = InnerText;
|
|
node = base.InsertAfter(newChild, refChild);
|
|
ResetOwnerElementInElementIdAttrMap(innerText);
|
|
}
|
|
else {
|
|
node = base.InsertAfter(newChild, refChild);
|
|
}
|
|
return node;
|
|
}
|
|
|
|
public override XmlNode ReplaceChild(XmlNode newChild, XmlNode oldChild) {
|
|
XmlNode node;
|
|
if (PrepareOwnerElementInElementIdAttrMap()) {
|
|
string innerText = InnerText;
|
|
node = base.ReplaceChild(newChild, oldChild);
|
|
ResetOwnerElementInElementIdAttrMap(innerText);
|
|
}
|
|
else {
|
|
node = base.ReplaceChild(newChild, oldChild);
|
|
}
|
|
return node;
|
|
}
|
|
|
|
public override XmlNode RemoveChild(XmlNode oldChild) {
|
|
XmlNode node;
|
|
if (PrepareOwnerElementInElementIdAttrMap()) {
|
|
string innerText = InnerText;
|
|
node = base.RemoveChild(oldChild);
|
|
ResetOwnerElementInElementIdAttrMap(innerText);
|
|
}
|
|
else {
|
|
node = base.RemoveChild(oldChild);
|
|
}
|
|
return node;
|
|
}
|
|
|
|
public override XmlNode PrependChild(XmlNode newChild) {
|
|
XmlNode node;
|
|
if (PrepareOwnerElementInElementIdAttrMap()) {
|
|
string innerText = InnerText;
|
|
node = base.PrependChild(newChild);
|
|
ResetOwnerElementInElementIdAttrMap(innerText);
|
|
}
|
|
else {
|
|
node = base.PrependChild(newChild);
|
|
}
|
|
return node;
|
|
}
|
|
|
|
public override XmlNode AppendChild(XmlNode newChild) {
|
|
XmlNode node;
|
|
if (PrepareOwnerElementInElementIdAttrMap()) {
|
|
string innerText = InnerText;
|
|
node = base.AppendChild(newChild);
|
|
ResetOwnerElementInElementIdAttrMap(innerText);
|
|
}
|
|
else {
|
|
node = base.AppendChild(newChild);
|
|
}
|
|
return node;
|
|
}
|
|
|
|
// DOM Level 2
|
|
|
|
// Gets the XmlElement node that contains this attribute.
|
|
public virtual XmlElement OwnerElement {
|
|
get {
|
|
return parentNode as XmlElement;
|
|
}
|
|
}
|
|
|
|
// Gets or sets the markup representing just the children of this node.
|
|
public override string InnerXml {
|
|
set {
|
|
RemoveAll();
|
|
XmlLoader loader = new XmlLoader();
|
|
loader.LoadInnerXmlAttribute( this, value );
|
|
}
|
|
}
|
|
|
|
// Saves the node to the specified XmlWriter.
|
|
public override void WriteTo(XmlWriter w) {
|
|
w.WriteStartAttribute( Prefix, LocalName, NamespaceURI );
|
|
WriteContentTo(w);
|
|
w.WriteEndAttribute();
|
|
}
|
|
|
|
// Saves all the children of the node to the specified XmlWriter.
|
|
public override void WriteContentTo(XmlWriter w) {
|
|
for (XmlNode node = FirstChild; node != null; node = node.NextSibling) {
|
|
node.WriteTo(w);
|
|
}
|
|
}
|
|
|
|
public override String BaseURI {
|
|
get {
|
|
if ( OwnerElement != null )
|
|
return OwnerElement.BaseURI;
|
|
return String.Empty;
|
|
}
|
|
}
|
|
|
|
internal override void SetParent(XmlNode node) {
|
|
this.parentNode = node;
|
|
}
|
|
|
|
internal override XmlSpace XmlSpace {
|
|
get {
|
|
if ( OwnerElement != null )
|
|
return OwnerElement.XmlSpace;
|
|
return XmlSpace.None;
|
|
}
|
|
}
|
|
|
|
internal override String XmlLang {
|
|
get {
|
|
if ( OwnerElement != null )
|
|
return OwnerElement.XmlLang;
|
|
return String.Empty;
|
|
}
|
|
}
|
|
internal override XPathNodeType XPNodeType {
|
|
get {
|
|
if (IsNamespace) {
|
|
return XPathNodeType.Namespace;
|
|
}
|
|
return XPathNodeType.Attribute;
|
|
}
|
|
}
|
|
|
|
internal override string XPLocalName {
|
|
get {
|
|
if (name.Prefix.Length == 0 && name.LocalName == "xmlns") return string.Empty;
|
|
return name.LocalName;
|
|
}
|
|
}
|
|
|
|
internal bool IsNamespace {
|
|
get {
|
|
return Ref.Equal(name.NamespaceURI, name.OwnerDocument.strReservedXmlns);
|
|
}
|
|
}
|
|
}
|
|
}
|