using System.Collections.Generic; using System.Xml; using System.Xml.Linq; using System.Xml.XPath; using XNeedle; using XNeedle.Parser.Elements; namespace XNeedle.Transformation { public class Rule : Part { public required string XPathSelector { get; set; } public required IEnumerable Body; public void Transform(XDocument xml, SourceLocation sloc) { var context = new Context(); context.Node = xml.Root; context.SLoc = sloc; Operate(context); } public override void Operate(Context ctx) { var nodes = ctx.Node?.XPathSelectElements(XPathSelector); if(nodes is null || nodes.Count() == 0) { var nullCtx = ctx.Clone(); nullCtx.Node = null; nullCtx.SLoc = ctx.SLoc.WithLineNumber(-1); foreach (var b in Body) { b.Operate(nullCtx); } return; } foreach (XElement n in nodes) { var loopCtx = ctx.Clone(); loopCtx.Node = n; var lineInfo = (IXmlLineInfo)n; loopCtx.SLoc = ctx.SLoc.WithLineNumber(lineInfo.HasLineInfo() ? lineInfo.LineNumber : -1); foreach (var b in Body) { b.Operate(loopCtx); } } } } }