Skip to content

XamlWriter bug causes loss of spaces #4410

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
vsfeedback opened this issue Apr 15, 2021 · 2 comments
Open

XamlWriter bug causes loss of spaces #4410

vsfeedback opened this issue Apr 15, 2021 · 2 comments
Assignees
Milestone

Comments

@vsfeedback
Copy link

This issue has been moved from a ticket on Developer Community.


[severity:Other]
Create a FlowDocument containing the Paragraph:

var p = new Paragraph(new Run(" A "));

(note the spaces before and after the text)

XamlWriter.Save will serialize this Paragraph as:

 A 

(note that the Run element was optimized out)

Now create a Paragraph with TWO Runs:

var p = new Paragraph();
p.Inlines.Add(new Run(" A "));
p.Inlines.Add(new Run(" B "));

(Yes, this could be done with a single Run, but the bug happens whether or not the second Run has artifacts like FontWeight, and it was simpler to demonstrate without.)

XamlWriter.Save will serialize this second Paragraph as:

 A  B 

Notice that the first Run was optimized out -- along with its xml:space attribute.
Removal of the xml:space attribute will now cause loss of the spaces when the XML is parsed back into a FlowDocument.

It does work correctly if the document is manually de-optimized by wrapping each Run with its own Span, but does not work if any Span contains more than one Run: The same optimization (and bug) occurs within each Span.

When used as part of a data-entry application, the arbitrary removal of user-entered spaces is less than ideal.


Original Comments

Feedback Bot on 4/13/2021, 03:53 AM:

We have directed your feedback to the appropriate engineering team for further evaluation. The team will review the feedback and notify you about the next steps.


Original Solutions

Bhavya Udayashankar [MSFT] solved on 4/13/2021, 11:45 AM, 0 votes:

Thank you for your feedback. This is not a VisualStudio issue but an issue with XamlWriter itself. Please file a ticket with that product at https://github.com/dotnet/wpf/issues. (https://aka.ms/vsfeedbackguidelines#other-product).

Thank you,
Bhavya

@lindexi
Copy link
Member

lindexi commented Apr 15, 2021

It is a feature, not a bug

See White-space processing in XAML - XAML | Microsoft Docs

@BrophyJeff
Copy link

The White-space processing IS the bug. This is not a feature.
My guess is that this issue is also present in Core and .NET5 - but I have not tested there yet.

The above examples are not showing the serialized XML markup, so I will try to repeat here using regular parentheses instead of angle brackets so you can see what I'm talking about:

In the first example:
var p = new Paragraph(new Run(" A "));
There is a space in the text content before and after the 'A'.
When serialized by XamlWriter, the correct xml:space="preserve" attribute is added to the Paragraph element because the Run element was optimized out:
(Paragraph xml:space="preserve") A (/Paragraph)

In the second example:
'var p = new Paragraph();
p.Inlines.Add(new Run(" A "));
p.Inlines.Add(new Run(" B "));'
This time there are two Runs with spaces in both the Runs.

Simple serialization would create two Run elements, each with the xml:space attribute:
(Paragraph)(Run xml:space="preserve") A (/Run)(Run xml:space="preserve") B (/Run)(/Paragraph)

BUT there is an optimization "feature" in the XamlWriter (as seen above) where a Run with no font/style changes is sometimes removed from the markup, and is implied by the Paragraph element directly containing text. This is a good optimization, because most of the time Run elements will inherit the style settings from the owning Paragraph.

With the optimization, you might expect the following serialization:
(Paragraph xml:space="preserve") A (Run xml:space="preserve") B (/Run)(/Paragraph)
or (because I didn't change the font on Run #2):
(Paragraph xml:space="preserve") A B (/Paragraph)

But the above markup is NOT what is produced.
Instead, only the first Run is optimized out and you get:
(Paragraph) A (Run xml:space="preserve") B (/Run)(/Paragraph)

Note that although the first Run's text was moved to the Paragraph, the xml:space attribute was not applied to the Paragraph.

When XamlReader is then used to retrieve the FlowDocument content, the whitespace in the first Run is removed (correctly) per the White-space processing rules. So the bug is in XamlWriter, not XamlReader.

@ryalanms ryalanms self-assigned this May 6, 2021
@ryalanms ryalanms added this to the 7.0.0 milestone Sep 2, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants