From a5b201d09577d6e5fbb10a3473375c483bdbc578 Mon Sep 17 00:00:00 2001 From: cx-ricardop Date: Wed, 4 Dec 2024 10:20:15 +0000 Subject: [PATCH] bug fix and ut's --- src/HtmlAgilityPack.Shared/HtmlDocument.cs | 2 +- src/HtmlAgilityPack.Shared/HtmlNode.cs | 55 +++++++++++++------ .../HtmlDocument.PreserveOriginalTest.cs | 50 +++++++++++++++++ 3 files changed, 88 insertions(+), 19 deletions(-) diff --git a/src/HtmlAgilityPack.Shared/HtmlDocument.cs b/src/HtmlAgilityPack.Shared/HtmlDocument.cs index d97fa23d..32656b80 100644 --- a/src/HtmlAgilityPack.Shared/HtmlDocument.cs +++ b/src/HtmlAgilityPack.Shared/HtmlDocument.cs @@ -1867,7 +1867,7 @@ private void PushAttributeNameStart(int index, int lineposition) _currentattribute.Line = _line; _currentattribute._lineposition = lineposition; _currentattribute._streamposition = index; - _currentattribute.InternalQuoteType = AttributeValueQuote.WithoutValue; + //_currentattribute.InternalQuoteType = AttributeValueQuote.WithoutValue; } private void PushAttributeValueEnd(int index) diff --git a/src/HtmlAgilityPack.Shared/HtmlNode.cs b/src/HtmlAgilityPack.Shared/HtmlNode.cs index dd4ce703..c8dfd7c4 100644 --- a/src/HtmlAgilityPack.Shared/HtmlNode.cs +++ b/src/HtmlAgilityPack.Shared/HtmlNode.cs @@ -2415,7 +2415,24 @@ internal void WriteAttribute(TextWriter outText, HtmlAttribute att) var isWithoutValue = quoteType == AttributeValueQuote.WithoutValue; string name; - string quote = quoteType == AttributeValueQuote.DoubleQuote ? "\"" : quoteType == AttributeValueQuote.SingleQuote ? "'" : ""; + string quote; + switch (quoteType) + { + case AttributeValueQuote.DoubleQuote: + case AttributeValueQuote.Initial: + case AttributeValueQuote.WithoutValue: + quote = "\""; + break; + case AttributeValueQuote.SingleQuote: + quote = "'"; + break; + case AttributeValueQuote.None: + default: + quote = ""; + break; + } + + if (_ownerdocument.OptionOutputAsXml) { if(quoteType != AttributeValueQuote.DoubleQuote && quoteType != AttributeValueQuote.SingleQuote) @@ -2457,24 +2474,26 @@ internal void WriteAttribute(TextWriter outText, HtmlAttribute att) } } - if (!isWithoutValue) - { - var value = quoteType == AttributeValueQuote.DoubleQuote ? !att.Value.StartsWith("@") ? att.Value.Replace("\"", """) : - att.Value : quoteType == AttributeValueQuote.SingleQuote ? att.Value.Replace("'", "'") : att.Value; - if (_ownerdocument.OptionOutputOptimizeAttributeValues) - if (att.Value.IndexOfAny(new char[] {(char) 10, (char) 13, (char) 9, ' '}) < 0) - outText.Write(" " + name + "=" + att.Value); - else - outText.Write(" " + name + "=" + quote + value + quote); - else - outText.Write(" " + name + "=" + quote + value + quote); - } - else + if (isWithoutValue) { - outText.Write(" " + name); - } - - } + outText.Write(" " + name); + } + else + { + var value = quoteType == AttributeValueQuote.DoubleQuote + ? !att.Value.StartsWith("@") ? att.Value.Replace("\"", """) : att.Value + : quoteType == AttributeValueQuote.SingleQuote + ? att.Value.Replace("'", "'") + : att.Value; + if (_ownerdocument.OptionOutputOptimizeAttributeValues) + if (att.Value.IndexOfAny(new char[] { (char)10, (char)13, (char)9, ' ' }) < 0) + outText.Write(" " + name + "=" + att.Value); + else + outText.Write(" " + name + "=" + quote + value + quote); + else + outText.Write(" " + name + "=" + quote + value + quote); + } + } } internal void WriteAttributes(TextWriter outText, bool closing) diff --git a/src/Tests/HtmlAgilityPack.Tests.NetStandard2_0/HtmlDocument.PreserveOriginalTest.cs b/src/Tests/HtmlAgilityPack.Tests.NetStandard2_0/HtmlDocument.PreserveOriginalTest.cs index 02ead6fa..fdd37ae1 100644 --- a/src/Tests/HtmlAgilityPack.Tests.NetStandard2_0/HtmlDocument.PreserveOriginalTest.cs +++ b/src/Tests/HtmlAgilityPack.Tests.NetStandard2_0/HtmlDocument.PreserveOriginalTest.cs @@ -161,6 +161,31 @@ public void PreserveClonedEmptyAttributesTest() Assert.Equal(@"", cloned.OuterHtml); } + [Fact] + public void PreserveEmptyAttributesWithInitialTest() + { + var d = new HtmlDocument(); + d.LoadHtml(""); + + var node = d.DocumentNode.SelectSingleNode("//bar"); + var outer = node.OuterHtml; + + Assert.Equal("", outer); + } + + [Fact] + public void PreserveEmptyAttributes() + { + var d = new HtmlDocument { GlobalAttributeValueQuote = AttributeValueQuote.Initial }; + d.LoadHtml("
  • Nothing to show
  • "); + + var node = d.DocumentNode.SelectSingleNode("//li"); + var outer = node.OuterHtml; + + Assert.Equal($"
  • Nothing to show
  • ", outer); + } + + [Fact] public void PreserveQuoteTypeForLoadedAttributes() { @@ -173,5 +198,30 @@ public void PreserveQuoteTypeForLoadedAttributes() // Result is: QuoteType: WithoutValue Assert.Equal(AttributeValueQuote.WithoutValue, checkedAttribute.QuoteType); } + + [Fact] + public void PreserveQuoteTypeForLoadedAttributes2() + { + var d = new HtmlDocument { GlobalAttributeValueQuote = AttributeValueQuote.Initial }; + d.LoadHtml(@""); + + var node = d.DocumentNode.SelectSingleNode("//bar"); + var outer = node.OuterHtml; + + Assert.Equal($"", outer); + } + + [Fact] + public void PreserveQuoteTypeForLoadedAttributes3() + { + var input = HtmlNode.CreateNode(@""); + var firstAttribute = input.Attributes.First(); + var secondAttribute = input.Attributes.LastOrDefault(); + + Assert.Equal("", firstAttribute.Value); + Assert.Equal(AttributeValueQuote.DoubleQuote, firstAttribute.QuoteType); + Assert.Equal("message", secondAttribute.Value); + Assert.Equal(AttributeValueQuote.SingleQuote, secondAttribute.QuoteType); + } } } \ No newline at end of file