| File: System\Xml\Linq\XAttribute.cs | Web Access |
| Project: src\runtime\src\libraries\System.Private.Xml.Linq\src\System.Private.Xml.Linq.csproj (System.Private.Xml.Linq) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; using CultureInfo = System.Globalization.CultureInfo; using SuppressMessageAttribute = System.Diagnostics.CodeAnalysis.SuppressMessageAttribute; namespace System.Xml.Linq { /// <summary> /// Represents an XML attribute. /// </summary> /// <remarks> /// An XML attribute is a name/value pair associated with an XML element. /// </remarks> [System.ComponentModel.TypeDescriptionProvider("MS.Internal.Xml.Linq.ComponentModel.XTypeDescriptionProvider`1[[System.Xml.Linq.XAttribute, System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]],System.ComponentModel.TypeConverter")] public class XAttribute : XObject { /// <summary> /// Gets an empty collection of attributes. /// </summary> public static IEnumerable<XAttribute> EmptySequence { get { return Array.Empty<XAttribute>(); } } internal XAttribute? next; internal XName name; internal string value; /// <overloads> /// Initializes a new instance of the <see cref="XAttribute"/> class. /// </overloads> /// <summary> /// Initializes a new instance of the <see cref="XAttribute"/> class from /// the specified name and value. /// </summary> /// <param name="name"> /// The name of the attribute. /// </param> /// <param name="value"> /// The value of the attribute. /// </param> /// <exception cref="ArgumentNullException"> /// Thrown if the passed in name or value are null. /// </exception> public XAttribute(XName name, object value) { ArgumentNullException.ThrowIfNull(name); ArgumentNullException.ThrowIfNull(value); string s = XContainer.GetStringValue(value); ValidateAttribute(name, s); this.name = name; this.value = s; } /// <summary> /// Initializes an instance of the XAttribute class /// from another XAttribute object. /// </summary> /// <param name="other"><see cref="XAttribute"/> object to copy from.</param> /// <exception cref="ArgumentNullException"> /// Thrown if the specified <see cref="XAttribute"/> is null. /// </exception> public XAttribute(XAttribute other) { ArgumentNullException.ThrowIfNull(other); name = other.name; value = other.value; } /// <summary> /// Gets a value indicating if this attribute is a namespace declaration. /// </summary> public bool IsNamespaceDeclaration { get { string namespaceName = name.NamespaceName; if (namespaceName.Length == 0) { return name.LocalName == "xmlns"; } return (object)namespaceName == (object)XNamespace.xmlnsPrefixNamespace; } } /// <summary> /// Gets the name of this attribute. /// </summary> public XName Name { get { return name; } } /// <summary> /// Gets the next attribute of the parent element. /// </summary> /// <remarks> /// If this attribute does not have a parent, or if there is no next attribute, /// then this property returns null. /// </remarks> public XAttribute? NextAttribute { get { return parent != null && ((XElement)parent).lastAttr != this ? next : null; } } /// <summary> /// Gets the node type for this node. /// </summary> /// <remarks> /// This property will always return XmlNodeType.Attribute. /// </remarks> public override XmlNodeType NodeType { get { return XmlNodeType.Attribute; } } /// <summary> /// Gets the previous attribute of the parent element. /// </summary> /// <remarks> /// If this attribute does not have a parent, or if there is no previous attribute, /// then this property returns null. /// </remarks> public XAttribute? PreviousAttribute { get { if (parent == null) return null; XAttribute a = ((XElement)parent).lastAttr!; while (a.next != this) { a = a.next!; } return a != ((XElement)parent).lastAttr ? a : null; } } /// <summary> /// Gets or sets the value of this attribute. /// </summary> /// <exception cref="ArgumentNullException"> /// Thrown if the value set is null. /// </exception> public string Value { get { return value; } set { ArgumentNullException.ThrowIfNull(value); ValidateAttribute(name, value); bool notify = NotifyChanging(this, XObjectChangeEventArgs.Value); this.value = value; if (notify) NotifyChanged(this, XObjectChangeEventArgs.Value); } } /// <summary> /// Deletes this XAttribute. /// </summary> /// <exception cref="InvalidOperationException"> /// Thrown if the parent element is null. /// </exception> public void Remove() { if (parent == null) throw new InvalidOperationException(SR.InvalidOperation_MissingParent); ((XElement)parent).RemoveAttribute(this); } /// <summary> /// Sets the value of this <see cref="XAttribute"/>. /// <seealso cref="XElement.SetValue"/> /// <seealso cref="XElement.SetAttributeValue"/> /// <seealso cref="XElement.SetElementValue"/> /// </summary> /// <param name="value"> /// The value to assign to this attribute. The value is converted to its string /// representation and assigned to the <see cref="Value"/> property. /// </param> /// <exception cref="ArgumentNullException"> /// Thrown if the specified value is null. /// </exception> public void SetValue(object value) { ArgumentNullException.ThrowIfNull(value); Value = XContainer.GetStringValue(value); } /// <summary> /// Override for <see cref="ToString()"/> on <see cref="XAttribute"/> /// </summary> /// <returns>XML text representation of an attribute and its value</returns> public override string ToString() { using (StringWriter sw = new StringWriter(CultureInfo.InvariantCulture)) { XmlWriterSettings ws = new XmlWriterSettings(); ws.ConformanceLevel = ConformanceLevel.Fragment; using (XmlWriter w = XmlWriter.Create(sw, ws)) { w.WriteAttributeString(GetPrefixOfNamespace(name.Namespace), name.LocalName, name.NamespaceName, value); } return sw.ToString().Trim(); } } /// <summary> /// Cast the value of this <see cref="XAttribute"/> to a <see cref="string"/>. /// </summary> /// <param name="attribute"> /// The <see cref="XAttribute"/> to cast to <see cref="string"/>. /// </param> /// <returns> /// The content of this <see cref="XAttribute"/> as a <see cref="string"/>. /// </returns> [CLSCompliant(false)] [return: NotNullIfNotNull(nameof(attribute))] public static explicit operator string?(XAttribute? attribute) { if (attribute == null) return null; return attribute.value; } /// <summary> /// Cast the value of this <see cref="XAttribute"/> to a <see cref="bool"/>. /// </summary> /// <param name="attribute"> /// The <see cref="XAttribute"/> to cast to <see cref="bool"/>. /// </param> /// <returns> /// The content of this <see cref="XAttribute"/> as a <see cref="bool"/>. /// </returns> /// <exception cref="ArgumentNullException"> /// Thrown if the specified attribute is null. /// </exception> [CLSCompliant(false)] public static explicit operator bool(XAttribute attribute) { ArgumentNullException.ThrowIfNull(attribute); return XmlConvert.ToBoolean(attribute.value.ToLowerInvariant()); } /// <summary> /// Cast the value of this <see cref="XAttribute"/> to a <see cref="bool"/>?. /// </summary> /// <param name="attribute"> /// The <see cref="XAttribute"/> to cast to <see cref="bool"/>?. Can be null. /// </param> /// <returns> /// The content of this <see cref="XAttribute"/> as a <see cref="bool"/>?. /// </returns> [CLSCompliant(false)] [return: NotNullIfNotNull(nameof(attribute))] public static explicit operator bool?(XAttribute? attribute) { if (attribute == null) return null; return XmlConvert.ToBoolean(attribute.value.ToLowerInvariant()); } /// <summary> /// Cast the value of this <see cref="XAttribute"/> to an <see cref="int"/>. /// </summary> /// <param name="attribute"> /// The <see cref="XAttribute"/> to cast to <see cref="int"/>. /// </param> /// <returns> /// The content of this <see cref="XAttribute"/> as an <see cref="int"/>. /// </returns> /// <exception cref="ArgumentNullException"> /// Thrown if the specified attribute is null. /// </exception> [CLSCompliant(false)] public static explicit operator int(XAttribute attribute) { ArgumentNullException.ThrowIfNull(attribute); return XmlConvert.ToInt32(attribute.value); } /// <summary> /// Cast the value of this <see cref="XAttribute"/> to an <see cref="int"/>?. /// </summary> /// <param name="attribute"> /// The <see cref="XAttribute"/> to cast to <see cref="int"/>?. Can be null. /// </param> /// <returns> /// The content of this <see cref="XAttribute"/> as an <see cref="int"/>?. /// </returns> [CLSCompliant(false)] [return: NotNullIfNotNull(nameof(attribute))] public static explicit operator int?(XAttribute? attribute) { if (attribute == null) return null; return XmlConvert.ToInt32(attribute.value); } /// <summary> /// Cast the value of this <see cref="XAttribute"/> to an <see cref="uint"/>. /// </summary> /// <param name="attribute"> /// The <see cref="XAttribute"/> to cast to <see cref="uint"/>. /// </param> /// <returns> /// The content of this <see cref="XAttribute"/> as an <see cref="uint"/>. /// </returns> /// <exception cref="ArgumentNullException"> /// Thrown if the specified attribute is null. /// </exception> [CLSCompliant(false)] public static explicit operator uint(XAttribute attribute) { ArgumentNullException.ThrowIfNull(attribute); return XmlConvert.ToUInt32(attribute.value); } /// <summary> /// Cast the value of this <see cref="XAttribute"/> to an <see cref="uint"/>?. /// </summary> /// <param name="attribute"> /// The <see cref="XAttribute"/> to cast to <see cref="uint"/>?. Can be null. /// </param> /// <returns> /// The content of this <see cref="XAttribute"/> as an <see cref="uint"/>?. /// </returns> [CLSCompliant(false)] [return: NotNullIfNotNull(nameof(attribute))] public static explicit operator uint?(XAttribute? attribute) { if (attribute == null) return null; return XmlConvert.ToUInt32(attribute.value); } /// <summary> /// Cast the value of this <see cref="XAttribute"/> to a <see cref="long"/>. /// </summary> /// <param name="attribute"> /// The <see cref="XAttribute"/> to cast to <see cref="long"/>. /// </param> /// <returns> /// The content of this <see cref="XAttribute"/> as a <see cref="long"/>. /// </returns> /// <exception cref="ArgumentNullException"> /// Thrown if the specified attribute is null. /// </exception> [CLSCompliant(false)] public static explicit operator long(XAttribute attribute) { ArgumentNullException.ThrowIfNull(attribute); return XmlConvert.ToInt64(attribute.value); } /// <summary> /// Cast the value of this <see cref="XAttribute"/> to a <see cref="long"/>?. /// </summary> /// <param name="attribute"> /// The <see cref="XAttribute"/> to cast to <see cref="long"/>?. Can be null. /// </param> /// <returns> /// The content of this <see cref="XAttribute"/> as a <see cref="long"/>?. /// </returns> [CLSCompliant(false)] [return: NotNullIfNotNull(nameof(attribute))] public static explicit operator long?(XAttribute? attribute) { if (attribute == null) return null; return XmlConvert.ToInt64(attribute.value); } /// <summary> /// Cast the value of this <see cref="XAttribute"/> to an <see cref="ulong"/>. /// </summary> /// <param name="attribute"> /// The <see cref="XAttribute"/> to cast to <see cref="ulong"/>. /// </param> /// <returns> /// The content of this <see cref="XAttribute"/> as an <see cref="ulong"/>. /// </returns> /// <exception cref="ArgumentNullException"> /// Thrown if the specified attribute is null. /// </exception> [CLSCompliant(false)] public static explicit operator ulong(XAttribute attribute) { ArgumentNullException.ThrowIfNull(attribute); return XmlConvert.ToUInt64(attribute.value); } /// <summary> /// Cast the value of this <see cref="XAttribute"/> to an <see cref="ulong"/>?. /// </summary> /// <param name="attribute"> /// The <see cref="XAttribute"/> to cast to <see cref="ulong"/>?. Can be null. /// </param> /// <returns> /// The content of this <see cref="XAttribute"/> as an <see cref="ulong"/>?. /// </returns> [CLSCompliant(false)] [return: NotNullIfNotNull(nameof(attribute))] public static explicit operator ulong?(XAttribute? attribute) { if (attribute == null) return null; return XmlConvert.ToUInt64(attribute.value); } /// <summary> /// Cast the value of this <see cref="XAttribute"/> to a <see cref="float"/>. /// </summary> /// <param name="attribute"> /// The <see cref="XAttribute"/> to cast to <see cref="float"/>. /// </param> /// <returns> /// The content of this <see cref="XAttribute"/> as a <see cref="float"/>. /// </returns> /// <exception cref="ArgumentNullException"> /// Thrown if the specified attribute is null. /// </exception> [CLSCompliant(false)] public static explicit operator float(XAttribute attribute) { ArgumentNullException.ThrowIfNull(attribute); return XmlConvert.ToSingle(attribute.value); } /// <summary> /// Cast the value of this <see cref="XAttribute"/> to a <see cref="float"/>?. /// </summary> /// <param name="attribute"> /// The <see cref="XAttribute"/> to cast to <see cref="float"/>?. Can be null. /// </param> /// <returns> /// The content of this <see cref="XAttribute"/> as a <see cref="float"/>?. /// </returns> [CLSCompliant(false)] [return: NotNullIfNotNull(nameof(attribute))] public static explicit operator float?(XAttribute? attribute) { if (attribute == null) return null; return XmlConvert.ToSingle(attribute.value); } /// <summary> /// Cast the value of this <see cref="XAttribute"/> to a <see cref="double"/>. /// </summary> /// <param name="attribute"> /// The <see cref="XAttribute"/> to cast to <see cref="double"/>. /// </param> /// <returns> /// The content of this <see cref="XAttribute"/> as a <see cref="double"/>. /// </returns> /// <exception cref="ArgumentNullException"> /// Thrown if the specified attribute is null. /// </exception> [CLSCompliant(false)] public static explicit operator double(XAttribute attribute) { ArgumentNullException.ThrowIfNull(attribute); return XmlConvert.ToDouble(attribute.value); } /// <summary> /// Cast the value of this <see cref="XAttribute"/> to a <see cref="double"/>?. /// </summary> /// <param name="attribute"> /// The <see cref="XAttribute"/> to cast to <see cref="double"/>?. Can be null. /// </param> /// <returns> /// The content of this <see cref="XAttribute"/> as a <see cref="double"/>?. /// </returns> [CLSCompliant(false)] [return: NotNullIfNotNull(nameof(attribute))] public static explicit operator double?(XAttribute? attribute) { if (attribute == null) return null; return XmlConvert.ToDouble(attribute.value); } /// <summary> /// Cast the value of this <see cref="XAttribute"/> to a <see cref="decimal"/>. /// </summary> /// <param name="attribute"> /// The <see cref="XAttribute"/> to cast to <see cref="decimal"/>. /// </param> /// <returns> /// The content of this <see cref="XAttribute"/> as a <see cref="decimal"/>. /// </returns> /// <exception cref="ArgumentNullException"> /// Thrown if the specified attribute is null. /// </exception> [CLSCompliant(false)] public static explicit operator decimal(XAttribute attribute) { ArgumentNullException.ThrowIfNull(attribute); return XmlConvert.ToDecimal(attribute.value); } /// <summary> /// Cast the value of this <see cref="XAttribute"/> to a <see cref="decimal"/>?. /// </summary> /// <param name="attribute"> /// The <see cref="XAttribute"/> to cast to <see cref="decimal"/>?. Can be null. /// </param> /// <returns> /// The content of this <see cref="XAttribute"/> as a <see cref="decimal"/>?. /// </returns> [CLSCompliant(false)] [return: NotNullIfNotNull(nameof(attribute))] public static explicit operator decimal?(XAttribute? attribute) { if (attribute == null) return null; return XmlConvert.ToDecimal(attribute.value); } /// <summary> /// Cast the value of this <see cref="XAttribute"/> to a <see cref="DateTime"/>. /// </summary> /// <param name="attribute"> /// The <see cref="XAttribute"/> to cast to <see cref="DateTime"/>. /// </param> /// <returns> /// The content of this <see cref="XAttribute"/> as a <see cref="DateTime"/>. /// </returns> /// <exception cref="ArgumentNullException"> /// Thrown if the specified attribute is null. /// </exception> [CLSCompliant(false)] public static explicit operator DateTime(XAttribute attribute) { ArgumentNullException.ThrowIfNull(attribute); return DateTime.Parse(attribute.value, CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.RoundtripKind); } /// <summary> /// Cast the value of this <see cref="XAttribute"/> to a <see cref="DateTime"/>?. /// </summary> /// <param name="attribute"> /// The <see cref="XAttribute"/> to cast to <see cref="DateTime"/>?. Can be null. /// </param> /// <returns> /// The content of this <see cref="XAttribute"/> as a <see cref="DateTime"/>?. /// </returns> [CLSCompliant(false)] [return: NotNullIfNotNull(nameof(attribute))] public static explicit operator DateTime?(XAttribute? attribute) { if (attribute == null) return null; return DateTime.Parse(attribute.value, CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.RoundtripKind); } /// <summary> /// Cast the value of this <see cref="XAttribute"/> to a <see cref="DateTimeOffset"/>. /// </summary> /// <param name="attribute"> /// The <see cref="XAttribute"/> to cast to <see cref="DateTimeOffset"/>. /// </param> /// <returns> /// The content of this <see cref="XAttribute"/> as a <see cref="DateTimeOffset"/>. /// </returns> /// <exception cref="ArgumentNullException"> /// Thrown if the specified attribute is null. /// </exception> [CLSCompliant(false)] public static explicit operator DateTimeOffset(XAttribute attribute) { ArgumentNullException.ThrowIfNull(attribute); return XmlConvert.ToDateTimeOffset(attribute.value); } /// <summary> /// Cast the value of this <see cref="XAttribute"/> to a <see cref="DateTimeOffset"/>?. /// </summary> /// <param name="attribute"> /// The <see cref="XAttribute"/> to cast to <see cref="DateTimeOffset"/>?. Can be null. /// </param> /// <returns> /// The content of this <see cref="XAttribute"/> as a <see cref="DateTimeOffset"/>?. /// </returns> [CLSCompliant(false)] [return: NotNullIfNotNull(nameof(attribute))] public static explicit operator DateTimeOffset?(XAttribute? attribute) { if (attribute == null) return null; return XmlConvert.ToDateTimeOffset(attribute.value); } /// <summary> /// Cast the value of this <see cref="XAttribute"/> to a <see cref="TimeSpan"/>. /// </summary> /// <param name="attribute"> /// The <see cref="XAttribute"/> to cast to <see cref="TimeSpan"/>. /// </param> /// <returns> /// The content of this <see cref="XAttribute"/> as a <see cref="TimeSpan"/>. /// </returns> /// <exception cref="ArgumentNullException"> /// Thrown if the specified attribute is null. /// </exception> [CLSCompliant(false)] public static explicit operator TimeSpan(XAttribute attribute) { ArgumentNullException.ThrowIfNull(attribute); return XmlConvert.ToTimeSpan(attribute.value); } /// <summary> /// Cast the value of this <see cref="XAttribute"/> to a <see cref="TimeSpan"/>?. /// </summary> /// <param name="attribute"> /// The <see cref="XAttribute"/> to cast to <see cref="TimeSpan"/>?. Can be null. /// </param> /// <returns> /// The content of this <see cref="XAttribute"/> as a <see cref="TimeSpan"/>?. /// </returns> [CLSCompliant(false)] [return: NotNullIfNotNull(nameof(attribute))] public static explicit operator TimeSpan?(XAttribute? attribute) { if (attribute == null) return null; return XmlConvert.ToTimeSpan(attribute.value); } /// <summary> /// Cast the value of this <see cref="XAttribute"/> to a <see cref="Guid"/>. /// </summary> /// <param name="attribute"> /// The <see cref="XAttribute"/> to cast to <see cref="Guid"/>. /// </param> /// <returns> /// The content of this <see cref="XAttribute"/> as a <see cref="Guid"/>. /// </returns> /// <exception cref="ArgumentNullException"> /// Thrown if the specified attribute is null. /// </exception> [CLSCompliant(false)] public static explicit operator Guid(XAttribute attribute) { ArgumentNullException.ThrowIfNull(attribute); return XmlConvert.ToGuid(attribute.value); } /// <summary> /// Cast the value of this <see cref="XAttribute"/> to a <see cref="Guid"/>?. /// </summary> /// <param name="attribute"> /// The <see cref="XAttribute"/> to cast to <see cref="Guid"/>?. Can be null. /// </param> /// <returns> /// The content of this <see cref="XAttribute"/> as a <see cref="Guid"/>?. /// </returns> [CLSCompliant(false)] [return: NotNullIfNotNull(nameof(attribute))] public static explicit operator Guid?(XAttribute? attribute) { if (attribute == null) return null; return XmlConvert.ToGuid(attribute.value); } internal int GetDeepHashCode() { return name.GetHashCode() ^ value.GetHashCode(); } internal string? GetPrefixOfNamespace(XNamespace ns) { string namespaceName = ns.NamespaceName; if (namespaceName.Length == 0) return string.Empty; if (parent != null) return ((XElement)parent).GetPrefixOfNamespace(ns); if ((object)namespaceName == (object)XNamespace.xmlPrefixNamespace) return "xml"; if ((object)namespaceName == (object)XNamespace.xmlnsPrefixNamespace) return "xmlns"; return null; } private static void ValidateAttribute(XName name, string value) { // The following constraints apply for namespace declarations: string namespaceName = name.NamespaceName; if ((object)namespaceName == (object)XNamespace.xmlnsPrefixNamespace) { if (value.Length == 0) { // The empty namespace name can only be declared by // the default namespace declaration throw new ArgumentException(SR.Format(SR.Argument_NamespaceDeclarationPrefixed, name.LocalName)); } else if (value == XNamespace.xmlPrefixNamespace) { // 'http://www.w3.org/XML/1998/namespace' can only // be declared by the 'xml' prefix namespace declaration. if (name.LocalName != "xml") throw new ArgumentException(SR.Argument_NamespaceDeclarationXml); } else if (value == XNamespace.xmlnsPrefixNamespace) { // 'http://www.w3.org/2000/xmlns/' must not be declared // by any namespace declaration. throw new ArgumentException(SR.Argument_NamespaceDeclarationXmlns); } else { string localName = name.LocalName; if (localName == "xml") { // No other namespace name can be declared by the 'xml' // prefix namespace declaration. throw new ArgumentException(SR.Argument_NamespaceDeclarationXml); } else if (localName == "xmlns") { // The 'xmlns' prefix must not be declared. throw new ArgumentException(SR.Argument_NamespaceDeclarationXmlns); } } } else if (namespaceName.Length == 0 && name.LocalName == "xmlns") { if (value == XNamespace.xmlPrefixNamespace) { // 'http://www.w3.org/XML/1998/namespace' can only // be declared by the 'xml' prefix namespace declaration. throw new ArgumentException(SR.Argument_NamespaceDeclarationXml); } else if (value == XNamespace.xmlnsPrefixNamespace) { // 'http://www.w3.org/2000/xmlns/' must not be declared // by any namespace declaration. throw new ArgumentException(SR.Argument_NamespaceDeclarationXmlns); } } } } }