using System; using System.Linq; using System.Text; using Sprache; using XNeedle.Formats; using XNeedle.Parser; using XNeedle.Parser.Elements; namespace XNeedle.Transformation { public class ContextFunctions { public static string hex(Context ctx, double value) { uint v = (uint)value; return $"#x{v:X8}"; } public static double GetLevel(Context ctx) { int level = 0; System.Xml.Linq.XElement? n = ctx.Node; while (null != (n = n?.Parent)) level++; return level; } public static double crc(Context ctx) { if (ctx.Node is null) return 0; // Step 1: Render the element to a string, preserving source style var (writer, buffer) = XmlRoundtripWriter.CreateToString(ctx.SLoc.FilePath, ctx.SLoc.Encoding); ctx.Node.WriteTo(writer); writer.Flush(); string xml = buffer.ToString(); // Step 2: Extract all text after the opening tag through and including the closing tag string tagName = ctx.Node.Name.LocalName; string data = XmlFragParser.ChecksumData(tagName).Parse(xml); // Step 3: Digest into CRC32 using the source encoding var crc32 = new System.IO.Hashing.Crc32(); crc32.Append(ctx.SLoc.Encoding.GetBytes(data)); uint result = BitConverter.ToUInt32(crc32.GetCurrentHash()); return (double)result; } public static string text(Context ctx) { if (ctx.Node is null) return ""; return ctx.Node.Value; } public static string text(Context ctx, string txt) { if (ctx.Node is null) return ""; ctx.Node.SetValue(txt); return txt; } public static string cdata(Context ctx) { if (ctx.Node is null) return ""; var cdataNode = ctx.Node.Nodes().OfType().FirstOrDefault(); return cdataNode?.Value ?? ""; } public static string cdata(Context ctx, string txt) { if (ctx.Node is null) return ""; var cdataNode = ctx.Node.Nodes().OfType().FirstOrDefault(); if (cdataNode != null) { cdataNode.Value = txt; } else { ctx.Node.Add(new System.Xml.Linq.XCData(txt)); } return txt; } public static string attr(Context ctx, string name, string value) { if (ctx.Node is null) return ""; var attr = ctx.Node.Attribute(name); if (attr != null) { attr.Value = value; } else { ctx.Node.SetAttributeValue(name, value); } return ""; } public static string attr(Context ctx, string name) { var attr = ctx.Node?.Attribute(name); if (attr != null) { return attr.Value; } return ""; } } }