using System; using System.Xml; using System.Xml.Linq; using CommandLine; using Sprache; using XNeedle.Parser; using XNeedle.Parser.Elements; using XNeedle.Transformation; using XNeedle.Formats; namespace XNeedle { class Program { public class Options { [Value(0, MetaName = "xn", Required = true, HelpText = "XN transformation definition")] public string XnDefinition { get; set; } [Option('i', "input", HelpText = "Input XML file", Required = true)] public string Input { get; set; } [Option('o', "output", HelpText = "Output XML file", Required = true)] public string Output { get; set; } [Option('v', "verbose", Required = false, HelpText = "Set output to verbose messages.")] public bool Verbose { get; set; } } static void Main(string[] args) { CommandLine.Parser.Default.ParseArguments(args) .WithParsed(RunOptions) .WithNotParsed(HandleParseError); } static void RunOptions(Options opts) { // Auto-discover operations via reflection BangOperation.RegisterAll(); var rawSource = File.ReadAllText(opts.XnDefinition); var xnSource = XnParser.StripComments(rawSource); Rule masterRule; try { masterRule = (Rule)XnParser.RuleObject.Parse(xnSource); } catch (ParseException ex) { var lines = rawSource.Split('\n'); int line = ex.Position?.Line ?? -1; int col = ex.Position?.Column ?? -1; bool showPosition = (line != -1) && (col != -1); if (showPosition) { Console.Error.WriteLine($"{opts.XnDefinition}({line},{col}): parse error: {ex.Message}"); var srcLine = line <= lines.Length ? lines[line - 1].TrimEnd() : ""; var pointer = new string(' ', Math.Max(0, col - 1)) + "^"; Console.Error.WriteLine($" {srcLine}"); Console.Error.WriteLine($" {pointer}"); } else { Console.Error.WriteLine($"{opts.XnDefinition}: parse error: {ex.Message}"); } return; } var doc = XDocument.Load(opts.Input, LoadOptions.PreserveWhitespace); var encoding = XmlRoundtripWriter.DetectEncoding(File.ReadAllBytes(opts.Input)); var sloc = new SourceLocation(opts.Input, encoding); masterRule.Transform(doc, sloc); using var writer = XmlRoundtripWriter.Create(opts.Input, opts.Output); doc.WriteTo(writer); Console.WriteLine($"Applied \"{opts.XnDefinition}\" to \"{opts.Input}\" and saved result to \"{opts.Output}\""); } static void HandleParseError(IEnumerable errs) {} } }