RaUI/Source/MyDb/HtmlAgilityPack.Shared/HtmlAttribute.cs
鑫Intel a1d6dce946 ### 2021-08-03更新
------
#### MyDbV4    V3.0.2108.0301
- *.[新增]新增内置HtmlAgilityPack组件。
2021-08-30 19:47:56 +08:00

327 lines
8.6 KiB
C#

// Description: Html Agility Pack - HTML Parsers, selectors, traversors, manupulators.
// Website & Documentation: http://html-agility-pack.net
// Forum & Issues: https://github.com/zzzprojects/html-agility-pack
// License: https://github.com/zzzprojects/html-agility-pack/blob/master/LICENSE
// More projects: http://www.zzzprojects.com/
// Copyright ?ZZZ Projects Inc. 2014 - 2017. All rights reserved.
#region
using System;
using System.Diagnostics;
#endregion
// ReSharper disable InconsistentNaming
namespace HtmlAgilityPack
{
/// <summary>
/// Represents an HTML attribute.
/// </summary>
[DebuggerDisplay("Name: {OriginalName}, Value: {Value}")]
public class HtmlAttribute : IComparable
{
#region Fields
private int _line;
internal int _lineposition;
internal string _name;
internal int _namelength;
internal int _namestartindex;
internal HtmlDocument _ownerdocument; // attribute can exists without a node
internal HtmlNode _ownernode;
private AttributeValueQuote _quoteType = AttributeValueQuote.DoubleQuote;
internal int _streamposition;
internal string _value;
internal int _valuelength;
internal int _valuestartindex;
#endregion
#region Constructors
internal HtmlAttribute(HtmlDocument ownerdocument)
{
_ownerdocument = ownerdocument;
}
#endregion
#region Properties
/// <summary>
/// Gets the line number of this attribute in the document.
/// </summary>
public int Line
{
get { return _line; }
internal set { _line = value; }
}
/// <summary>
/// Gets the column number of this attribute in the document.
/// </summary>
public int LinePosition
{
get { return _lineposition; }
}
/// <summary>
/// Gets the stream position of the value of this attribute in the document, relative to the start of the document.
/// </summary>
public int ValueStartIndex
{
get { return _valuestartindex; }
}
/// <summary>
/// Gets the length of the value.
/// </summary>
public int ValueLength
{
get { return _valuelength; }
}
/// <summary>
///
/// </summary>
public bool UseOriginalName { get; set; } = false;
/// <summary>
/// Gets the qualified name of the attribute.
/// </summary>
public string Name
{
get
{
if (_name == null)
{
_name = _ownerdocument.Text.Substring(_namestartindex, _namelength);
}
return UseOriginalName ? _name : _name.ToLowerInvariant();
}
set
{
if (value == null)
{
throw new ArgumentNullException("value");
}
_name = value;
if (_ownernode != null)
{
_ownernode.SetChanged();
}
}
}
/// <summary>
/// Name of attribute with original case
/// </summary>
public string OriginalName
{
get { return _name; }
}
/// <summary>
/// Gets the HTML document to which this attribute belongs.
/// </summary>
public HtmlDocument OwnerDocument
{
get { return _ownerdocument; }
}
/// <summary>
/// Gets the HTML node to which this attribute belongs.
/// </summary>
public HtmlNode OwnerNode
{
get { return _ownernode; }
}
/// <summary>
/// Specifies what type of quote the data should be wrapped in
/// </summary>
public AttributeValueQuote QuoteType
{
get { return _quoteType; }
set { _quoteType = value; }
}
/// <summary>
/// Specifies what type of quote the data should be wrapped in (internal to keep backward compatibility)
/// </summary>
internal AttributeValueQuote InternalQuoteType { get; set; }
/// <summary>
/// Gets the stream position of this attribute in the document, relative to the start of the document.
/// </summary>
public int StreamPosition
{
get { return _streamposition; }
}
/// <summary>
/// Gets or sets the value of the attribute.
/// </summary>
public string Value
{
get
{
// A null value has been provided, the attribute should be considered as "hidden"
if (_value == null && _ownerdocument.Text == null && _valuestartindex == 0 && _valuelength == 0)
{
return null;
}
if (_value == null)
{
_value = _ownerdocument.Text.Substring(_valuestartindex, _valuelength);
if (!_ownerdocument.BackwardCompatibility)
{
_value = HtmlEntity.DeEntitize(_value);
}
}
return _value;
}
set
{
_value = value;
if (_ownernode != null)
{
_ownernode.SetChanged();
}
}
}
/// <summary>
/// Gets the DeEntitized value of the attribute.
/// </summary>
public string DeEntitizeValue
{
get { return HtmlEntity.DeEntitize(Value); }
}
internal string XmlName
{
get { return HtmlDocument.GetXmlName(Name, true, OwnerDocument.OptionPreserveXmlNamespaces); }
}
internal string XmlValue
{
get { return Value; }
}
/// <summary>
/// Gets a valid XPath string that points to this Attribute
/// </summary>
public string XPath
{
get
{
string basePath = (OwnerNode == null) ? "/" : OwnerNode.XPath + "/";
return basePath + GetRelativeXpath();
}
}
#endregion
#region IComparable Members
/// <summary>
/// Compares the current instance with another attribute. Comparison is based on attributes' name.
/// </summary>
/// <param name="obj">An attribute to compare with this instance.</param>
/// <returns>A 32-bit signed integer that indicates the relative order of the names comparison.</returns>
public int CompareTo(object obj)
{
HtmlAttribute att = obj as HtmlAttribute;
if (att == null)
{
throw new ArgumentException("obj");
}
return Name.CompareTo(att.Name);
}
#endregion
#region Public Methods
/// <summary>
/// Creates a duplicate of this attribute.
/// </summary>
/// <returns>The cloned attribute.</returns>
public HtmlAttribute Clone()
{
HtmlAttribute att = new HtmlAttribute(_ownerdocument);
att.Name = Name;
att.Value = Value;
att.QuoteType = QuoteType;
return att;
}
/// <summary>
/// Removes this attribute from it's parents collection
/// </summary>
public void Remove()
{
_ownernode.Attributes.Remove(this);
}
#endregion
#region Private Methods
private string GetRelativeXpath()
{
if (OwnerNode == null)
return Name;
int i = 1;
foreach (HtmlAttribute node in OwnerNode.Attributes)
{
if (node.Name != Name) continue;
if (node == this)
break;
i++;
}
return "@" + Name + "[" + i + "]";
}
#endregion
}
/// <summary>
/// An Enum representing different types of Quotes used for surrounding attribute values
/// </summary>
public enum AttributeValueQuote
{
/// <summary>
/// A single quote mark '
/// </summary>
SingleQuote,
/// <summary>
/// A double quote mark "
/// </summary>
DoubleQuote,
/// <summary>
/// No quote mark
/// </summary>
None,
/// <summary>
/// The initial value (current value)
/// </summary>
Initial
}
}