From 6b0b6515e14b87a29002cd10a111fcf81d6e29bc Mon Sep 17 00:00:00 2001 From: dajiaohuang Date: Wed, 21 Oct 2026 09:59:42 +0800 Subject: [PATCH] Preserve Glow metadata and template elements across XML round trips --- .../Xml/GlowXmlExport.cs | 2 +- .../Xml/GlowXmlImport.cs | 72 ++++++++++++++++--- tests/regressions/glow_xml_roundtrip.cs | 30 ++++++++ 3 files changed, 95 insertions(+), 9 deletions(-) create mode 100644 tests/regressions/glow_xml_roundtrip.cs diff --git a/EmberLib.net/EmberLib.Glow.PowerPack/Xml/GlowXmlExport.cs b/EmberLib.net/EmberLib.Glow.PowerPack/Xml/GlowXmlExport.cs index c2b71c93..13524c88 100644 --- a/EmberLib.net/EmberLib.Glow.PowerPack/Xml/GlowXmlExport.cs +++ b/EmberLib.net/EmberLib.Glow.PowerPack/Xml/GlowXmlExport.cs @@ -141,7 +141,7 @@ void ConvertParameter(GlowParameterBase glow, XmlWriter writer) glow.Step.Do(value => writer.WriteElementString("step", XmlConvert.ToString(value))); glow.Access.Do(value => writer.WriteElementString("access", XmlConvert.ToString(value))); glow.Type.Do(value => writer.WriteElementString("type", XmlConvert.ToString(value))); - glow.IsOnline.Do(value => writer.WriteElementString("isOnlin", XmlConvert.ToString(value))); + glow.IsOnline.Do(value => writer.WriteElementString("isOnline", XmlConvert.ToString(value))); glow.StreamIdentifier.Do(value => writer.WriteElementString("streamIdentifier", XmlConvert.ToString(value))); var enumMap = glow.EnumMap; diff --git a/EmberLib.net/EmberLib.Glow.PowerPack/Xml/GlowXmlImport.cs b/EmberLib.net/EmberLib.Glow.PowerPack/Xml/GlowXmlImport.cs index be077611..406238d7 100644 --- a/EmberLib.net/EmberLib.Glow.PowerPack/Xml/GlowXmlImport.cs +++ b/EmberLib.net/EmberLib.Glow.PowerPack/Xml/GlowXmlImport.cs @@ -75,6 +75,12 @@ GlowContainer Convert(XElement xml) case "QualifiedFunction": return ConvertQualifiedFunction(xml); + + case "Template": + return ConvertTemplate(xml); + + case "QualifiedTemplate": + return ConvertQualifiedTemplate(xml); } return null; @@ -245,23 +251,69 @@ GlowCommand ConvertCommand(XElement xml) return glow; } - GlowNode ConvertNode(XElement xml) + GlowTemplateBase ConvertTemplateBase(GlowTemplateBase glow, XElement xml) { - var glow = new GlowNode(XmlConvert.ToInt32(xml.Attribute("number").Value)); + var description = xml.Attribute("description"); + if(description != null) + glow.Description = description.Value; + + var elementXml = xml.Element("element"); + if(elementXml != null) + { + var element = elementXml.Elements().SingleOrDefault(); + if(element != null) + glow.Element = ConvertTemplateElement(element); + } + + return glow; + } + + GlowElement ConvertTemplateElement(XElement xml) + { + switch(xml.Name.LocalName) + { + case "Node": + return ConvertNode(xml, GlowTags.Template.Element); + case "Parameter": + return ConvertParameter(xml, GlowTags.Template.Element); + case "Matrix": + return ConvertMatrix(xml, GlowTags.Template.Element); + case "Function": + return ConvertFunction(xml, GlowTags.Template.Element); + } + + return null; + } + + GlowTemplate ConvertTemplate(XElement xml) + { + var glow = new GlowTemplate(XmlConvert.ToInt32(xml.Attribute("number").Value)); + return (GlowTemplate)ConvertTemplateBase(glow, xml); + } + + GlowQualifiedTemplate ConvertQualifiedTemplate(XElement xml) + { + var glow = new GlowQualifiedTemplate(ConvertPath(xml.Attribute("path").Value), null); + return (GlowQualifiedTemplate)ConvertTemplateBase(glow, xml); + } + + GlowNode ConvertNode(XElement xml, BerTag? tag = null) + { + var glow = new GlowNode(XmlConvert.ToInt32(xml.Attribute("number").Value), tag); FillNode(glow, xml); return glow; } - GlowParameter ConvertParameter(XElement xml) + GlowParameter ConvertParameter(XElement xml, BerTag? tag = null) { - var glow = new GlowParameter(XmlConvert.ToInt32(xml.Attribute("number").Value)); + var glow = new GlowParameter(XmlConvert.ToInt32(xml.Attribute("number").Value), tag); FillParameter(glow, xml); return glow; } - GlowMatrix ConvertMatrix(XElement xml) + GlowMatrix ConvertMatrix(XElement xml, BerTag? tag = null) { - var glow = new GlowMatrix(XmlConvert.ToInt32(xml.Attribute("number").Value)); + var glow = new GlowMatrix(XmlConvert.ToInt32(xml.Attribute("number").Value), tag); FillMatrix(glow, xml); return glow; } @@ -294,9 +346,9 @@ GlowContainer ConvertQualifiedFunction(XElement xml) return glow; } - GlowContainer ConvertFunction(XElement xml) + GlowFunction ConvertFunction(XElement xml, BerTag? tag = null) { - var glow = new GlowFunction(XmlConvert.ToInt32(xml.Attribute("number").Value)); + var glow = new GlowFunction(XmlConvert.ToInt32(xml.Attribute("number").Value), tag); FillFunction(glow, xml); return glow; } @@ -362,6 +414,10 @@ void FillParameter(GlowParameterBase glow, XElement xml) if(valueXml != null) glow.Value = ConvertValue(valueXml); + var defaultXml = contentsXml.Element("default"); + if(defaultXml != null) + glow.Default = ConvertValue(defaultXml); + var minimumXml = contentsXml.Element("minimum"); if(minimumXml != null) glow.Minimum = ConvertMinMax(minimumXml); diff --git a/tests/regressions/glow_xml_roundtrip.cs b/tests/regressions/glow_xml_roundtrip.cs new file mode 100644 index 00000000..f16b08ec --- /dev/null +++ b/tests/regressions/glow_xml_roundtrip.cs @@ -0,0 +1,30 @@ +using System; +using System.IO; +using System.Text; +using System.Xml; +using System.Globalization; +using EmberLib.Glow; +using EmberLib.Glow.PowerPack.Xml; +static class Program { + static GlowContainer RoundTrip(GlowContainer node) { + var text=new StringBuilder();using(var writer=XmlWriter.Create(text,new XmlWriterSettings{OmitXmlDeclaration=true}))GlowXmlExport.Export(node,writer); + using(var reader=XmlReader.Create(new StringReader(text.ToString())))return GlowXmlImport.Import(reader); + } + static int Main(string[] args) { + int bad=0;var parameter=new GlowParameter(1){IsOnline=false,Default=new GlowValue(5L)}; + var result=RoundTrip(parameter) as GlowParameter; + if(result==null||result.IsOnline!=false)bad++; + if(result==null||result.Default==null||result.Default.ToString(CultureInfo.InvariantCulture)!="5")bad++; + Console.WriteLine("parameter metadata mismatches="+bad); + foreach(var payload in new GlowElement[]{new GlowNode(2,GlowTags.Template.Element),new GlowParameter(2,GlowTags.Template.Element),new GlowMatrix(2,GlowTags.Template.Element),new GlowFunction(2,GlowTags.Template.Element)}) { + var template=new GlowTemplate(1){Description="native",Element=payload};var imported=RoundTrip(template) as GlowTemplate; + bool ok=imported!=null&&imported.Description=="native"&&imported.Element!=null&&imported.Element.GetType()==payload.GetType()&&imported.Element.Tag==GlowTags.Template.Element; + if(!ok)bad++;Console.WriteLine(payload.GetType().Name+" template parity="+ok); + } + var qualified=new GlowQualifiedTemplate(new[]{1,2},null){Description="qualified",Element=new GlowNode(3,GlowTags.Template.Element)}; + var q=RoundTrip(qualified) as GlowQualifiedTemplate; + if(q==null||q.Description!="qualified"||q.Element==null||q.Element.Tag!=GlowTags.Template.Element)bad++; + Console.WriteLine("Public Glow exporter→importer mismatches="+bad+"/7"); + return bad == 0 ? 0 : 1; + } +}