GerardSmit.Language.Xml 2.1.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package GerardSmit.Language.Xml --version 2.1.0
                    
NuGet\Install-Package GerardSmit.Language.Xml -Version 2.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="GerardSmit.Language.Xml" Version="2.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="GerardSmit.Language.Xml" Version="2.1.0" />
                    
Directory.Packages.props
<PackageReference Include="GerardSmit.Language.Xml" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add GerardSmit.Language.Xml --version 2.1.0
                    
#r "nuget: GerardSmit.Language.Xml, 2.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package GerardSmit.Language.Xml@2.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=GerardSmit.Language.Xml&version=2.1.0
                    
Install as a Cake Addin
#tool nuget:?package=GerardSmit.Language.Xml&version=2.1.0
                    
Install as a Cake Tool

XmlParser

This is a fork of the 'GuiLabs.Language.Xml' project. See KirillOsenkov/XmlParser for the original project. This project is not affiliated with the original project (the namespace and the project name are the same for compatibility reasons).

Changes

In comparison to the original project, this fork has the following changes:

  • Removed the interfaces IXmlElement and IXmlElementSyntax.
    Reason: this made editing the syntax tree more difficult, as the interfaces had to be cast to the SyntaxNode constantly. As replacement a new class called XmlElementBaseSyntax was introduced.

  • Added various enumerators for nodes, XML attributes and XML elements.
    Reason: before the iterator methods were used, which generated a state machine and allocates memory. The enumerators are more efficient and don't allocate memory.

    The enumerators also have their own First and FirstOrDefault, because reaching the LINQ ones boxes the enumerator.

  • Improved ReplaceNode for XML elements.
    Reason: Before a visitor was used to replace nodes, which allocated more memory and was less efficient.

  • Added the following utility methods:

    • GetOrAddElement - gets or adds an element to the XML tree, with support for paths. For example:
      root = root.GetOrAddElement("Project/PropertyGroup", out var propertyGroup);
      
    • SetAttribute - sets an attribute of an element. If the attribute does not exist, it is added.
      propertyGroup = propertyGroup.SetAttribute("TargetFramework", "net9.0");
      
    • GetElement / GetElements - the child elements with a given name, mirroring GetAttribute down to the optional prefix.
      XmlElementBaseSyntax propertyGroup = root.GetElement("PropertyGroup");
      
      foreach (XmlElementBaseSyntax reference in root.GetElements("PackageReference"))
      {
          // ...
      }
      
    • GetElementsByPath - every element reachable by a slash-separated child path. Unlike a hand-rolled walker, it expands every segment rather than taking the first match at each step, so a path crossing repeated ancestors sees all of them.
      foreach (XmlElementBaseSyntax ipSecurity in root.GetElementsByPath("location/system.webServer/security/ipSecurity"))
      {
          // one per <location>, not just the first
      }
      
    • GetIndentUnit, GetIndent and GetNewLine - what the document already does for formatting, so new nodes can be placed to match it without reimplementing NormalizeTrivia.
      string unit = root.GetIndentUnit();  // e.g. "    " or "\t"
      string newLine = root.GetNewLine();  // "\r\n" or "\n"
      

Original README:

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.

  • The parser produces a full-fidelity syntax tree, meaning every character of the source text is represented in the tree. The tree covers the entire source text.
  • The parser has no dependencies and can easily be made portable. I would appreciate a high quality pull request making the parser portable.
  • The parser is based on the section of the Roslyn VB parser that parses XML literals. The Roslyn code is ported to C# and is made standalone.
  • The parser is error-tolerant. It will still produce a full tree even from invalid XML with missing tags, extra invalid text, etc. Missing and skipped tokens are still represented in the tree.
  • The resulting tree is immutable and follows Roslyn's green/red separation for maximum reusability of nodes.
  • The parser has basic support for incrementality. Given a previous constructed tree and a list of changes it will try to reuse existing nodes and only re-create what is necessary.
  • This library is more low-level than XLinq (for instance XLinq doesn't seem to represent whitespace around attributes). Also it has no idea about XML namespaces and just tells you what's in the source text (whereas in XLinq there's too much ceremony around XML namespaces).

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

  • XML DTD is not supported (Roslyn didn't support it either)
  • Code wasn't tuned for performance and allocations, I'm sure a lot can be done to reduce memory consumption by the resulting tree. It should be pretty efficient though.
  • We reserve the right to accept only very high quality pull requests. We have very limited time to work on this so I ask everybody to please respect that.

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());
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on GerardSmit.Language.Xml:

Package Downloads
GerardSmit.Language.Xml.Roslyn

Conversions between GerardSmit.Language.Xml's TextSpan and Microsoft.CodeAnalysis.Text.TextSpan, for consumers turning parse results into editor ranges. Kept out of the core package so it stays dependency-free.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
3.0.0 457 8/22/2026
2.1.0 115 8/14/2026
2.0.8 745 4/18/2024
2.0.7 204 4/5/2024
2.0.6 239 4/5/2024
2.0.5 222 4/4/2024
2.0.4 212 4/4/2024
2.0.3 198 4/4/2024
2.0.2 226 4/4/2024
2.0.1 208 4/4/2024
2.0.0 207 4/4/2024