diff --git a/src/HtmlAgilityPack.Shared/HtmlAttribute.cs b/src/HtmlAgilityPack.Shared/HtmlAttribute.cs index bb2d2ff9..93853141 100644 --- a/src/HtmlAgilityPack.Shared/HtmlAttribute.cs +++ b/src/HtmlAgilityPack.Shared/HtmlAttribute.cs @@ -31,13 +31,13 @@ public class HtmlAttribute : IComparable internal int _namestartindex; internal HtmlDocument _ownerdocument; // attribute can exists without a node internal HtmlNode _ownernode; - private AttributeValueQuote _quoteType = AttributeValueQuote.DoubleQuote; + private AttributeValueQuote? _quoteType; internal int _streamposition; internal string _value; internal int _valuelength; internal int _valuestartindex; - internal bool _isFromParse; - internal bool _hasEqual; + //internal bool _isFromParse; + //internal bool _hasEqual; private bool? _localUseOriginalName; #endregion @@ -168,14 +168,14 @@ public HtmlNode OwnerNode /// public AttributeValueQuote QuoteType { - get { return _quoteType; } - set { _quoteType = value; } + get { return _quoteType ?? this.InternalQuoteType ?? this.OwnerDocument.GlobalAttributeValueQuote ?? AttributeValueQuote.DoubleQuote; } + set { _quoteType = value != AttributeValueQuote.Initial ? (AttributeValueQuote?)value : null; } } /// /// Specifies what type of quote the data should be wrapped in (internal to keep backward compatibility) /// - internal AttributeValueQuote InternalQuoteType { get; set; } + internal AttributeValueQuote? InternalQuoteType { get; set; } /// /// Gets the stream position of this attribute in the document, relative to the start of the document. @@ -213,6 +213,10 @@ public string Value set { _value = value; + if (!string.IsNullOrEmpty(_value) && this.QuoteType == AttributeValueQuote.WithoutValue) + { + this.InternalQuoteType = this.OwnerDocument.GlobalAttributeValueQuote ?? AttributeValueQuote.DoubleQuote; + } if (_ownernode != null) { @@ -284,11 +288,11 @@ public HtmlAttribute Clone() HtmlAttribute att = new HtmlAttribute(_ownerdocument); att.Name = OriginalName; att.Value = Value; - att.QuoteType = QuoteType; + att._quoteType = _quoteType; att.InternalQuoteType = InternalQuoteType; - att._isFromParse = _isFromParse; - att._hasEqual = _hasEqual; + //att._isFromParse = _isFromParse; + //att._hasEqual = _hasEqual; return att; } diff --git a/src/HtmlAgilityPack.Shared/HtmlDocument.cs b/src/HtmlAgilityPack.Shared/HtmlDocument.cs index b58dac1b..0ea38074 100644 --- a/src/HtmlAgilityPack.Shared/HtmlDocument.cs +++ b/src/HtmlAgilityPack.Shared/HtmlDocument.cs @@ -1503,7 +1503,7 @@ private void Parse() if (NewCheck()) continue; - _currentattribute._isFromParse = true; + //_currentattribute._isFromParse = true; // Add !,?,% and other special? @@ -1525,7 +1525,7 @@ private void Parse() if (_c == '=') { PushAttributeNameEnd(_index - 1); - _currentattribute._hasEqual = true; + //_currentattribute._hasEqual = true; _state = ParseState.AttributeAfterEquals; continue; } @@ -1573,7 +1573,7 @@ private void Parse() if (_c == '=') { - _currentattribute._hasEqual = true; + //_currentattribute._hasEqual = true; _state = ParseState.AttributeAfterEquals; continue; } @@ -1822,6 +1822,7 @@ private void PushAttributeNameStart(int index, int lineposition) _currentattribute.Line = _line; _currentattribute._lineposition = lineposition; _currentattribute._streamposition = index; + _currentattribute.InternalQuoteType = AttributeValueQuote.WithoutValue; } private void PushAttributeValueEnd(int index) @@ -2044,11 +2045,13 @@ private void PushAttributeValueStart(int index, int quote) _currentattribute._valuestartindex = index; if (quote == '\'') { - _currentattribute.QuoteType = AttributeValueQuote.SingleQuote; + _currentattribute.InternalQuoteType = AttributeValueQuote.SingleQuote; + } + if (quote == '"') + { + _currentattribute.InternalQuoteType = AttributeValueQuote.DoubleQuote; } - _currentattribute.InternalQuoteType = _currentattribute.QuoteType; - if (quote == 0) { _currentattribute.InternalQuoteType = AttributeValueQuote.None; diff --git a/src/HtmlAgilityPack.Shared/HtmlNode.cs b/src/HtmlAgilityPack.Shared/HtmlNode.cs index 184617df..fc6aaa31 100644 --- a/src/HtmlAgilityPack.Shared/HtmlNode.cs +++ b/src/HtmlAgilityPack.Shared/HtmlNode.cs @@ -2346,15 +2346,16 @@ internal void WriteAttribute(TextWriter outText, HtmlAttribute att) } var quoteType = OwnerDocument.GlobalAttributeValueQuote ?? att.QuoteType; - var isWithoutValue = quoteType == AttributeValueQuote.WithoutValue - || (quoteType == AttributeValueQuote.Initial && att._isFromParse && !att._hasEqual && string.IsNullOrEmpty(att.XmlValue)); + //var isWithoutValue = quoteType == AttributeValueQuote.WithoutValue + // || (quoteType == AttributeValueQuote.Initial && att._isFromParse && !att._hasEqual && string.IsNullOrEmpty(att.XmlValue)); - if (quoteType == AttributeValueQuote.Initial && !(att._isFromParse && !att._hasEqual && string.IsNullOrEmpty(att.XmlValue))) + if (quoteType == AttributeValueQuote.Initial/* && !(att._isFromParse && !att._hasEqual && string.IsNullOrEmpty(att.XmlValue))*/) { - quoteType = att.InternalQuoteType; + quoteType = att.QuoteType; } + var isWithoutValue = quoteType == AttributeValueQuote.WithoutValue; - string name; + string name; string quote = quoteType == AttributeValueQuote.DoubleQuote ? "\"" : quoteType == AttributeValueQuote.SingleQuote ? "'" : ""; if (_ownerdocument.OptionOutputAsXml) { diff --git a/src/Tests/HtmlAgilityPack.Tests.Net45/HtmlDocument.PreserveOriginalTest.cs b/src/Tests/HtmlAgilityPack.Tests.Net45/HtmlDocument.PreserveOriginalTest.cs index 6ab176e6..2b042bb3 100644 --- a/src/Tests/HtmlAgilityPack.Tests.Net45/HtmlDocument.PreserveOriginalTest.cs +++ b/src/Tests/HtmlAgilityPack.Tests.Net45/HtmlDocument.PreserveOriginalTest.cs @@ -1,9 +1,10 @@ using NUnit.Framework; using System; using System.IO; +using System.Linq; using System.Xml.XPath; -namespace HtmlAgilityPack.Tests.fx._4._5 +namespace HtmlAgilityPack.Tests { [TestFixture] public class HtmlDocumentPreserveOriginalTest @@ -168,5 +169,18 @@ public void PreserveClonedEmptyAttributesTest() Assert.AreEqual(@"", cloned.OuterHtml); } + + [Test] + public void PreserveQuoteTypeForLoadedAttributes() + { + var input = HtmlNode.CreateNode(""); + var checkedAttribute = input.Attributes.First(); + + // Result is: Value: '' (empty string) + Assert.AreEqual("", checkedAttribute.Value); + + // Result is: QuoteType: WithoutValue + Assert.AreEqual(AttributeValueQuote.WithoutValue, checkedAttribute.QuoteType); + } } } \ No newline at end of file diff --git a/src/Tests/HtmlAgilityPack.Tests.Net45/UnitTest1.cs b/src/Tests/HtmlAgilityPack.Tests.Net45/UnitTest1.cs index 651eb373..1281ea40 100644 --- a/src/Tests/HtmlAgilityPack.Tests.Net45/UnitTest1.cs +++ b/src/Tests/HtmlAgilityPack.Tests.Net45/UnitTest1.cs @@ -1,7 +1,7 @@ using System; using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace HtmlAgilityPack.Tests.fx._4._5 +namespace HtmlAgilityPack.Tests { [TestClass] public class UnitTest1 diff --git a/src/Tests/HtmlAgilityPack.Tests.Net45/files/attr_quote.html b/src/Tests/HtmlAgilityPack.Tests.Net45/files/attr_quote.html index c14c3d4b..416e1623 100644 --- a/src/Tests/HtmlAgilityPack.Tests.Net45/files/attr_quote.html +++ b/src/Tests/HtmlAgilityPack.Tests.Net45/files/attr_quote.html @@ -1,4 +1,4 @@ - 
+ diff --git a/src/Tests/HtmlAgilityPack.Tests.Net45/files/attr_quote_expected.html b/src/Tests/HtmlAgilityPack.Tests.Net45/files/attr_quote_expected.html index 1564f485..a687b75b 100644 --- a/src/Tests/HtmlAgilityPack.Tests.Net45/files/attr_quote_expected.html +++ b/src/Tests/HtmlAgilityPack.Tests.Net45/files/attr_quote_expected.html @@ -1,4 +1,4 @@ - + @@ -22,7 +22,7 @@ {{ dimension.code }} - {{ dimension.description }} - {{ simulationRequest.categoriaBemId | commonData:lea546CATBEM$:'id':'code-desc' }} + {{ simulationRequest.categoriaBemId | commonData:lea546CATBEM$:'id':'code-desc' }}