diff --git a/YangParser/Generator/YangGenerator.cs b/YangParser/Generator/YangGenerator.cs index 1c3aaba..e1a6ffa 100644 --- a/YangParser/Generator/YangGenerator.cs +++ b/YangParser/Generator/YangGenerator.cs @@ -363,6 +363,11 @@ public class TargetAttribute(string xPath) : Attribute { public string XPath { get; } = xPath; } + [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] + public class XPathAttribute(string path) : Attribute + { + public string Path { get; } = path; + } [AttributeUsage(AttributeTargets.All, AllowMultiple = false)] public class KeyAttribute(params string[] value) : Attribute { diff --git a/YangParser/SemanticModel/Action.cs b/YangParser/SemanticModel/Action.cs index e316217..13e2a5e 100644 --- a/YangParser/SemanticModel/Action.cs +++ b/YangParser/SemanticModel/Action.cs @@ -43,7 +43,7 @@ public override string ToCode() builder.AppendLine( $"public static {returnType} {MakeName(Argument)}(IChannel channel, int messageID{inputType})"); builder.AppendLine("{"); - var ns = Parent is Module module ? "xmlns=\\\"" + module.XmlNamespace.Argument + "\\\"" : string.Empty; + var ns = Parent is Module module ? $"xmlns:{module.XmlNamespace?.Prefix}=\\\"" + module.XmlNamespace?.Namespace + "\\\"" : string.Empty; builder.AppendLine(inputType != string.Empty ? $$""" var xml = $"<{{Argument}} {{ns}}>{input.ToXML()}"; diff --git a/YangParser/SemanticModel/BelongsTo.cs b/YangParser/SemanticModel/BelongsTo.cs index de285f1..e91b0d8 100644 --- a/YangParser/SemanticModel/BelongsTo.cs +++ b/YangParser/SemanticModel/BelongsTo.cs @@ -14,7 +14,7 @@ public BelongsTo(YangStatement statement) : base(statement) public override ChildRule[] PermittedChildren { get; } = [ - new ChildRule(Prefix.Keyword, Cardinality.Required) + new ChildRule(SemanticModel.Prefix.Keyword, Cardinality.Required) ]; public override string ToCode() diff --git a/YangParser/SemanticModel/Grouping.cs b/YangParser/SemanticModel/Grouping.cs index 714f936..34b727d 100644 --- a/YangParser/SemanticModel/Grouping.cs +++ b/YangParser/SemanticModel/Grouping.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using YangParser.Generator; using YangParser.Parser; @@ -41,7 +40,7 @@ public override string ToCode() public IStatement[] WithUse(Uses use) { var copy = StatementFactory.Create(Source); - Parent.Insert([copy]); + Parent!.Insert([copy]); copy.Parent = Parent; foreach (var child in copy.Unwrap()) { @@ -123,12 +122,13 @@ public IStatement[] WithUse(Uses use) var current = copy; foreach (var element in path) { - var prefix = element.Prefix(out var name); + element.Prefix(out var name); var origin = current; current = origin.Children.FirstOrDefault(c => c.Argument == name); if (current is null) { - Log.Write($"Could not find part '{name}' of path {refinement.Argument} in source {origin}"); + Log.Write( + $"Could not find part '{name}' of path {refinement.Argument} in source {origin.Source.Keyword} {origin.Argument}"); break; //Target not present, nothing to refine. } } diff --git a/YangParser/SemanticModel/IStatement.cs b/YangParser/SemanticModel/IStatement.cs index ae5515d..e2b73de 100644 --- a/YangParser/SemanticModel/IStatement.cs +++ b/YangParser/SemanticModel/IStatement.cs @@ -5,7 +5,7 @@ namespace YangParser.SemanticModel; public interface IStatement { - string Argument { get; set; } + string Argument { get; set; } ChildRule[] PermittedChildren { get; } HashSet Attributes { get; } HashSet Keywords { get; } @@ -18,6 +18,9 @@ public interface IStatement string ToCode(); void Replace(IStatement child, IEnumerable replacements); void Insert(IEnumerable augments); + string XPath { get; } + (string Namespace, string Prefix)? XmlNamespace { get; set; } + string Prefix { get; } } public interface ICommentable : IStatement diff --git a/YangParser/SemanticModel/Import.cs b/YangParser/SemanticModel/Import.cs index 56410cd..b4bdc15 100644 --- a/YangParser/SemanticModel/Import.cs +++ b/YangParser/SemanticModel/Import.cs @@ -10,19 +10,8 @@ public Import(YangStatement statement) : base(statement) { if (statement.Keyword != Keyword) throw new SemanticError($"Non-matching Keyword '{statement.Keyword}', expected {Keyword}", statement); - - Revision = Children.FirstOrDefault(child => child is RevisionDate)?.Argument; - Prefix = Children.First(child => child is Prefix).Argument; - var reference = Children.FirstOrDefault(child => child is Reference); - var description = Children.FirstOrDefault(child => child is Description); - AdditionalInformation = reference is null ? string.Empty : $"Reference: \"{reference.Argument}\", "; - AdditionalInformation += description is null ? string.Empty : $"Description: \"{description}\""; } - private readonly string? Revision; - private readonly string Prefix; - private readonly string? AdditionalInformation; - public const string Keyword = "import"; public override ChildRule[] PermittedChildren { get; } = diff --git a/YangParser/SemanticModel/Module.cs b/YangParser/SemanticModel/Module.cs index ab9cc4f..49fb196 100644 --- a/YangParser/SemanticModel/Module.cs +++ b/YangParser/SemanticModel/Module.cs @@ -11,9 +11,9 @@ public Module(YangStatement statement) : base(statement) { if (statement.Keyword != Keyword) throw new SemanticError($"Non-matching Keyword '{statement.Keyword}', expected {Keyword}", statement); - XmlNamespace = Children.First(child => child is Namespace); var localPrefix = this.GetChild().Argument; var localNS = MakeNamespace(Argument) + ".YangNode."; + XmlNamespace = (Children.First(child => child is Namespace).Argument, localPrefix); Usings = new() { [localPrefix] = localNS @@ -64,9 +64,6 @@ public Module(YangStatement statement) : base(statement) } public Dictionary ImportedModules { get; } = []; - - - public IStatement XmlNamespace { get; set; } public Dictionary Usings { get; } public string Namespace { get; private set; } @@ -91,7 +88,7 @@ public Module(YangStatement statement) : base(statement) new ChildRule(SemanticModel.Namespace.Keyword, Cardinality.Required), new ChildRule(Notification.Keyword, Cardinality.ZeroOrMore), new ChildRule(Organization.Keyword), - new ChildRule(Prefix.Keyword, Cardinality.Required), + new ChildRule(SemanticModel.Prefix.Keyword, Cardinality.Required), new ChildRule(Reference.Keyword), new ChildRule(Revision.Keyword, Cardinality.ZeroOrMore), new ChildRule(Rpc.Keyword, Cardinality.ZeroOrMore), diff --git a/YangParser/SemanticModel/Rpc.cs b/YangParser/SemanticModel/Rpc.cs index 8a1cc3d..1238671 100644 --- a/YangParser/SemanticModel/Rpc.cs +++ b/YangParser/SemanticModel/Rpc.cs @@ -54,7 +54,7 @@ public override string ToCode() builder.AppendLine( $"public static {returnType} {MakeName(Argument)}(IChannel channel, int messageID{inputType})"); builder.AppendLine("{"); - var ns = Parent is Module module ? "xmlns=\\\"" + module.XmlNamespace.Argument + "\\\"" : string.Empty; + var ns = Parent is Module module ? $"xmlns:{module.XmlNamespace?.Prefix}=\\\"" + module.XmlNamespace?.Namespace + "\\\"" : string.Empty; builder.AppendLine(inputType != string.Empty ? $$""" var xml = $"<{{Argument}} {{ns}}>{input.ToXML()}"; diff --git a/YangParser/SemanticModel/Statement.cs b/YangParser/SemanticModel/Statement.cs index b458565..3b78f78 100644 --- a/YangParser/SemanticModel/Statement.cs +++ b/YangParser/SemanticModel/Statement.cs @@ -5,6 +5,7 @@ using System.Text.RegularExpressions; using YangParser.Parser; using YangParser.SemanticModel.Builtins; +using String = System.String; namespace YangParser.SemanticModel; @@ -23,6 +24,12 @@ protected Statement(YangStatement statement, bool validate = true) Children = statement.Children.Select(StatementFactory.Create).ToArray(); } + public (string Namespace, string Prefix)? XmlNamespace { get; set; } + public string Prefix => XmlNamespace?.Prefix ?? Parent?.Prefix ?? string.Empty; + + public string XPath => ((Parent?.XPath ?? String.Empty) + "/").Replace("//", "/") + + (string.IsNullOrEmpty(Prefix) ? string.Empty : Prefix + ":") + Source.Argument; + public YangStatement Source { get; set; } private IStatement[] _children = []; @@ -76,7 +83,7 @@ public static string MakeName(string argument) var prefix = argument.Prefix(out var value); var addColon = !prefix.Contains('.') && !string.IsNullOrWhiteSpace(prefix); - foreach (var section in value.Split('-', ' ', '/', '.','^')) + foreach (var section in value.Split('-', ' ', '/', '.', '^')) { output.Append(Capitalize(section)); } @@ -124,9 +131,14 @@ protected static string TypeName(Type type) protected string KeywordString => " " + string.Join(" ", Keywords) + (Keywords.Count > 0 ? " " : ""); - public string AttributeString => Attributes.Count > 0 - ? "\n" + string.Join("\n", Attributes.OrderBy(x => x.Length).Select(attr => $"[{attr}]")) - : string.Empty; + public string AttributeString + { + get + { + Attributes.Add("XPath(\"" + XPath + '"' + ')'); + return "\n" + string.Join("\n", Attributes.OrderBy(x => x.Length).Select(attr => $"[{attr}]")); + } + } public string DescriptionString => $""" ///