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 @@
-