From cc8738c0dce5770ff3a8aa35d692a84c9481c100 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominic=20H=C3=B6glinger?= Date: Thu, 23 Apr 2026 20:20:56 +0200 Subject: [PATCH] Use LINQ XDocument --- Parser/Elements/Context.cs | 5 +-- Program.cs | 28 +++++++++++-- Transformation/ContextFunctions.cs | 63 +++++------------------------- Transformation/Rule.cs | 10 +++-- 4 files changed, 41 insertions(+), 65 deletions(-) diff --git a/Parser/Elements/Context.cs b/Parser/Elements/Context.cs index 71948ed..53d9057 100644 --- a/Parser/Elements/Context.cs +++ b/Parser/Elements/Context.cs @@ -1,12 +1,11 @@ -using System.Xml; +using System.Xml.Linq; namespace XNeedle.Parser.Elements { public class Context { public string? XPathSelector { get; set; } - public XmlNodeList? Nodes { get; set; } - public XmlNode? Node { get; set; } + public XElement? Node { get; set; } public Context Clone() { diff --git a/Program.cs b/Program.cs index 2ad603a..d99dd33 100644 --- a/Program.cs +++ b/Program.cs @@ -35,15 +35,35 @@ namespace XNeedle static void RunOptions(Options opts) { var masterRule = (Rule)XnParser.RuleObject.Parse(File.ReadAllText(opts.XnDefinition)); - var doc = new XmlDocument(); - doc.PreserveWhitespace = true; - doc.Load(opts.Input); + var doc = XDocument.Load(opts.Input, LoadOptions.PreserveWhitespace); masterRule.Transform(doc); - doc.Save(opts.Output); + doc.Save(opts.Output, SaveOptions.DisableFormatting); Console.WriteLine($"Applied \"{opts.XnDefinition}\" to \"{opts.Input}\" and saved result to \"{opts.Output}\""); } static void HandleParseError(IEnumerable errs) {} } + + public static class DocumentExtensions + { + public static XmlDocument ToXmlDocument(this XDocument xDocument) + { + var xmlDocument = new XmlDocument(); + using(var xmlReader = xDocument.CreateReader()) + { + xmlDocument.Load(xmlReader); + } + return xmlDocument; + } + + public static XDocument ToXDocument(this XmlDocument xmlDocument) + { + using (var nodeReader = new XmlNodeReader(xmlDocument)) + { + nodeReader.MoveToContent(); + return XDocument.Load(nodeReader); + } + } + } } \ No newline at end of file diff --git a/Transformation/ContextFunctions.cs b/Transformation/ContextFunctions.cs index 517d3ab..ad100ea 100644 --- a/Transformation/ContextFunctions.cs +++ b/Transformation/ContextFunctions.cs @@ -33,88 +33,43 @@ namespace XNeedle.Transformation } int crc = 0xAFFE; - XmlWriterSettings settings = new XmlWriterSettings(); - settings.Indent = true; - settings.ConformanceLevel = ConformanceLevel.Document; - settings.OmitXmlDeclaration = true; - - // This isn't performant, but the whole document has to be rendered - // for an accurate data stream - string docrender = ""; - string fragrender = ""; - using (var sw = new StringWriter()) - { - using (var xw = XmlWriter.Create(sw, settings)) - { - if (ctx.Node.OwnerDocument is not null) - { - ctx.Node.OwnerDocument.WriteContentTo(xw); - } - } - docrender = sw.ToString(); - } - - settings.Indent = false; - settings.ConformanceLevel = ConformanceLevel.Fragment; - using (var sw = new StringWriter()) - { - using (var xw = XmlWriter.Create(sw, settings)) - { - ctx.Node.WriteTo(xw); - } - fragrender = sw.ToString(); - } - string tagname = ctx.Node.Name; - string anchor = XmlFragParser.OpeningTagAnchor(tagname).Parse(fragrender); - string preamble = $"<{tagname}{anchor}>"; - - //string data = FragXmlParser.ChecksumData(preamble, tagname).TryParse(docrender); - - Console.WriteLine("preamble: " + preamble); - - var crc32 = new System.IO.Hashing.Crc32(); - var bytes = Encoding.UTF8.GetBytes(""); - crc32.Append(bytes); - crc = BitConverter.ToInt32(crc32.GetCurrentHash()); - return (double)crc; } public static string text(Context ctx) { if (ctx.Node is null) return ""; - return ctx.Node.InnerText; + return ctx.Node.Value; } public static string text(Context ctx, string txt) { if (ctx.Node is null) return ""; - return ctx.Node.InnerText = txt; + ctx.Node.SetValue(txt); + return txt; } public static string attr(Context ctx, string name, string value) { - if (ctx.Node is null || ctx.Node.Attributes is null) return ""; - var attr = ctx.Node.Attributes[name]; + if (ctx.Node is null || !ctx.Node.HasAttributes) return ""; + var attr = ctx.Node.Attribute(name); if (attr != null) { attr.Value = value; } else { - if (ctx.Node.OwnerDocument is null) return ""; - var add = ctx.Node.OwnerDocument.CreateAttribute(name); - add.Value = value; - ctx.Node.Attributes.SetNamedItem(add); + ctx.Node.SetAttributeValue(name, value); } return ""; } public static string attr(Context ctx, string name) { - if (ctx.Node?.Attributes?[name]?.Value is string val) + var attr = ctx.Node?.Attribute(name); + if (attr != null) { - return val; + return attr.Value; } return ""; } diff --git a/Transformation/Rule.cs b/Transformation/Rule.cs index 30bfb12..961844c 100644 --- a/Transformation/Rule.cs +++ b/Transformation/Rule.cs @@ -1,5 +1,7 @@ using System.Collections.Generic; using System.Xml; +using System.Xml.Linq; +using System.Xml.XPath; using XNeedle.Parser.Elements; namespace XNeedle.Transformation @@ -9,10 +11,10 @@ namespace XNeedle.Transformation public required string XPathSelector { get; set; } public required IEnumerable Body; - public void Transform(XmlDocument xml) + public void Transform(XDocument xml) { var context = new Context(); - context.Node = xml.DocumentElement; + context.Node = xml.Root; Operate(context); } @@ -22,12 +24,12 @@ namespace XNeedle.Transformation { return; } - var nodes = ctx.Node.SelectNodes(XPathSelector); + var nodes = ctx.Node.XPathSelectElements(XPathSelector); if(nodes is null) { return; } - foreach (XmlNode n in nodes) + foreach (XElement n in nodes) { var loopCtx = ctx.Clone(); loopCtx.Node = n;