Use LINQ XDocument

This commit is contained in:
Dominic Höglinger 2026-04-23 20:20:56 +02:00
parent 13e375c145
commit cc8738c0dc
4 changed files with 41 additions and 65 deletions

View File

@ -1,12 +1,11 @@
using System.Xml; using System.Xml.Linq;
namespace XNeedle.Parser.Elements namespace XNeedle.Parser.Elements
{ {
public class Context public class Context
{ {
public string? XPathSelector { get; set; } public string? XPathSelector { get; set; }
public XmlNodeList? Nodes { get; set; } public XElement? Node { get; set; }
public XmlNode? Node { get; set; }
public Context Clone() public Context Clone()
{ {

View File

@ -35,15 +35,35 @@ namespace XNeedle
static void RunOptions(Options opts) static void RunOptions(Options opts)
{ {
var masterRule = (Rule)XnParser.RuleObject.Parse(File.ReadAllText(opts.XnDefinition)); var masterRule = (Rule)XnParser.RuleObject.Parse(File.ReadAllText(opts.XnDefinition));
var doc = new XmlDocument(); var doc = XDocument.Load(opts.Input, LoadOptions.PreserveWhitespace);
doc.PreserveWhitespace = true;
doc.Load(opts.Input);
masterRule.Transform(doc); 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}\""); Console.WriteLine($"Applied \"{opts.XnDefinition}\" to \"{opts.Input}\" and saved result to \"{opts.Output}\"");
} }
static void HandleParseError(IEnumerable<Error> errs) {} static void HandleParseError(IEnumerable<Error> 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);
}
}
}
} }

View File

@ -33,88 +33,43 @@ namespace XNeedle.Transformation
} }
int crc = 0xAFFE; 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; return (double)crc;
} }
public static string text(Context ctx) public static string text(Context ctx)
{ {
if (ctx.Node is null) return ""; if (ctx.Node is null) return "";
return ctx.Node.InnerText; return ctx.Node.Value;
} }
public static string text(Context ctx, string txt) public static string text(Context ctx, string txt)
{ {
if (ctx.Node is null) return ""; 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) public static string attr(Context ctx, string name, string value)
{ {
if (ctx.Node is null || ctx.Node.Attributes is null) return ""; if (ctx.Node is null || !ctx.Node.HasAttributes) return "";
var attr = ctx.Node.Attributes[name]; var attr = ctx.Node.Attribute(name);
if (attr != null) if (attr != null)
{ {
attr.Value = value; attr.Value = value;
} }
else else
{ {
if (ctx.Node.OwnerDocument is null) return ""; ctx.Node.SetAttributeValue(name, value);
var add = ctx.Node.OwnerDocument.CreateAttribute(name);
add.Value = value;
ctx.Node.Attributes.SetNamedItem(add);
} }
return ""; return "";
} }
public static string attr(Context ctx, string name) 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 ""; return "";
} }

View File

@ -1,5 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Xml; using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;
using XNeedle.Parser.Elements; using XNeedle.Parser.Elements;
namespace XNeedle.Transformation namespace XNeedle.Transformation
@ -9,10 +11,10 @@ namespace XNeedle.Transformation
public required string XPathSelector { get; set; } public required string XPathSelector { get; set; }
public required IEnumerable<Part> Body; public required IEnumerable<Part> Body;
public void Transform(XmlDocument xml) public void Transform(XDocument xml)
{ {
var context = new Context(); var context = new Context();
context.Node = xml.DocumentElement; context.Node = xml.Root;
Operate(context); Operate(context);
} }
@ -22,12 +24,12 @@ namespace XNeedle.Transformation
{ {
return; return;
} }
var nodes = ctx.Node.SelectNodes(XPathSelector); var nodes = ctx.Node.XPathSelectElements(XPathSelector);
if(nodes is null) if(nodes is null)
{ {
return; return;
} }
foreach (XmlNode n in nodes) foreach (XElement n in nodes)
{ {
var loopCtx = ctx.Clone(); var loopCtx = ctx.Clone();
loopCtx.Node = n; loopCtx.Node = n;