KirillOsenkov / XmlParser

A Roslyn-inspired full-fidelity XML parser with no dependencies and a simple Visual Studio XML language service
Apache License 2.0
325 stars 49 forks source link

XmlParser

logo image

Build status NuGet package NuGet package for VS Editor

A Roslyn-inspired full-fidelity XML parser with no dependencies and a simple Visual Studio XML language service.

This is work in progress and by no means complete. Specifically:

Download from NuGet:

Try it!

https://xmlsyntaxvisualizer.azurewebsites.net/index.html

The above app leverages the parser and can help you visualize the resulting syntax tree generated from an XML document.

Code is available at https://github.com/garuma/XmlSyntaxVisualizer C# UWP example at https://github.com/michael-hawker/XmlSyntaxVisualizerUWP

Also see the blog post: https://blog.neteril.org/blog/2018/03/21/xml-parsing-roslyn/

Resources about Immutable Syntax Trees: https://github.com/KirillOsenkov/Bliki/wiki/Roslyn-Immutable-Trees

FAQ:

How to find a node in the tree given a position in the source text?

https://github.com/KirillOsenkov/XmlParser/blob/master/src/Microsoft.Language.Xml/Utilities/SyntaxLocator.cs#L24

SyntaxLocator.FindNode(SyntaxNode node, int position);

How to replace a node in the tree

var original = """
               <Project Sdk="Microsoft.NET.Sdk">
                 <PropertyGroup>
                   <TargetFramework>net8.0</TargetFramework>
                 </PropertyGroup>
               </Project>
               """;

var expected = """
               <Project Sdk="Microsoft.NET.Sdk">
                 <PropertyGroup>
                   <TargetFramework>net9.0</TargetFramework>
                 </PropertyGroup>
               </Project>
               """;

XmlDocumentSyntax root = Parser.ParseText(original);
XmlElementSyntax syntaxToReplace = root
    .Descendants()
    .OfType<XmlElementSyntax>()
    .Single(n => n.Name == "TargetFramework");
SyntaxNode textSyntaxToReplace = syntaxToReplace.Content.Single();

XmlTextSyntax content = SyntaxFactory.XmlText(SyntaxFactory.XmlTextLiteralToken("net9.0", null, null));

root = root.ReplaceNode(textSyntaxToReplace, content);

Assert.Equal(expected, root.ToFullString());