|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Text;
namespace System.Xml
{
// Represents the xml declaration nodes: <?xml version='1.0' ...?>
public class XmlDeclaration : XmlLinkedNode
{
private const string YES = "yes";
private const string NO = "no";
private string _version;
private string _encoding;
private string _standalone;
protected internal XmlDeclaration(string version, string? encoding, string? standalone, XmlDocument doc) : base(doc)
{
if (!IsValidXmlVersion(version))
throw new ArgumentException(SR.Xdom_Version);
if ((standalone != null) && (standalone.Length > 0))
if ((standalone != YES) && (standalone != NO))
throw new ArgumentException(SR.Format(SR.Xdom_standalone, standalone));
this.Encoding = encoding;
this.Standalone = standalone;
this.Version = version;
}
// The version attribute for <?xml version= '1.0' ... ?>
public string Version
{
get { return _version; }
[MemberNotNull(nameof(_version))]
internal set { _version = value; }
}
// Specifies the value of the encoding attribute, as for
// <?xml version= '1.0' encoding= 'UTF-8' ?>
[AllowNull]
public string Encoding
{
get { return _encoding; }
[MemberNotNull(nameof(_encoding))]
set { _encoding = value ?? string.Empty; }
}
// Specifies the value of the standalone attribute.
[AllowNull]
public string Standalone
{
get { return _standalone; }
[MemberNotNull(nameof(_standalone))]
set
{
if (value == null)
_standalone = string.Empty;
else if (value.Length == 0 || value == YES || value == NO)
_standalone = value;
else
throw new ArgumentException(SR.Format(SR.Xdom_standalone, value));
}
}
public override string? Value
{
get { return InnerText; }
set { InnerText = value!; }
}
// Gets or sets the concatenated values of the node and
// all its children.
public override string InnerText
{
get
{
var strb = new ValueStringBuilder(stackalloc char[256]);
strb.Append("version=\"");
strb.Append(Version);
strb.Append('"');
if (Encoding.Length > 0)
{
strb.Append(" encoding=\"");
strb.Append(Encoding);
strb.Append('"');
}
if (Standalone.Length > 0)
{
strb.Append(" standalone=\"");
strb.Append(Standalone);
strb.Append('"');
}
return strb.ToString();
}
set
{
string? tempVersion;
string? tempEncoding;
string? tempStandalone;
string orgEncoding = this.Encoding;
string orgStandalone = this.Standalone;
string? orgVersion = this.Version;
XmlLoader.ParseXmlDeclarationValue(value, out tempVersion, out tempEncoding, out tempStandalone);
try
{
if (tempVersion != null && !IsValidXmlVersion(tempVersion))
throw new ArgumentException(SR.Xdom_Version);
Version = tempVersion!;
if (tempEncoding != null)
Encoding = tempEncoding;
if (tempStandalone != null)
Standalone = tempStandalone;
}
catch
{
Encoding = orgEncoding;
Standalone = orgStandalone;
Version = orgVersion;
throw;
}
}
}
//override methods and properties from XmlNode
// Gets the name of the node.
public override string Name
{
get
{
return "xml";
}
}
// Gets the name of the current node without the namespace prefix.
public override string LocalName
{
get { return Name; }
}
// Gets the type of the current node.
public override XmlNodeType NodeType
{
get { return XmlNodeType.XmlDeclaration; }
}
// Creates a duplicate of this node.
public override XmlNode CloneNode(bool deep)
{
Debug.Assert(OwnerDocument != null);
return OwnerDocument.CreateXmlDeclaration(Version, Encoding, Standalone);
}
// Saves the node to the specified XmlWriter.
public override void WriteTo(XmlWriter w)
{
w.WriteProcessingInstruction(Name, InnerText);
}
// Saves all the children of the node to the specified XmlWriter.
public override void WriteContentTo(XmlWriter w)
{
// Intentionally do nothing since the node doesn't have children.
}
private static bool IsValidXmlVersion(string ver)
{
return ver.Length >= 3 && ver[0] == '1' && ver[1] == '.' && XmlCharType.IsOnlyDigits(ver, 2, ver.Length - 2);
}
}
}
|