MODULE XMLTransformer;
IMPORT
Strings, XML, XMLObjects, Commands, Files, Modules;
TYPE
String = Strings.String;
XMLPluginProcInfo = POINTER TO RECORD
name, procedure : ARRAY 128 OF CHAR;
next : XMLPluginProcInfo;
END;
TransformProc = PROCEDURE (element : XML.Element) : XML.Container;
VAR
xmlPluginProcs : XMLPluginProcInfo;
PROCEDURE Transform*(elem : XML.Element) : XML.Container;
VAR
transformProc : TransformProc;
container : XML.Container;
s, name : String;
BEGIN
s := elem.GetName();
name := Strings.UpperCaseInNew(s^);
transformProc := FindProcedure(name^);
IF transformProc # NIL THEN
RETURN transformProc(elem);
ELSE
NEW(container);
RETURN container;
END;
END Transform;
PROCEDURE AddContentsOf*(source, target : XML.Container);
VAR
enum: XMLObjects.Enumerator;
p : ANY;
BEGIN
enum := source.GetContents();
WHILE (enum.HasMoreElements()) DO
p := enum.GetNext();
target.AddContent(p(XML.Content));
END;
END AddContentsOf;
PROCEDURE TransformElemsIn*(container : XML.Container) : XML.Container;
VAR
c : XML.Container;
enum: XMLObjects.Enumerator;
p : ANY;
BEGIN
NEW(c);
enum := container.GetContents();
WHILE (enum.HasMoreElements()) DO
p := enum.GetNext();
IF p IS XML.Element THEN
AddContentsOf(Transform(p(XML.Element)), c);
END;
END;
RETURN c;
END TransformElemsIn;
PROCEDURE GetNewParagraph*(style : ARRAY OF CHAR) : XML.Element;
VAR
paragraph : XML.Element;
styleAttrPar : XML.Attribute;
s : String;
BEGIN
NEW(paragraph); paragraph.SetName("Paragraph");
NEW(styleAttrPar); s := Strings.NewString("style"); styleAttrPar.SetName(s^);
styleAttrPar.SetValue(style);
paragraph.AddAttribute(styleAttrPar);
RETURN paragraph;
END GetNewParagraph;
PROCEDURE GetNewSpan*(style : ARRAY OF CHAR) : XML.Element;
VAR
span : XML.Element;
styleAttrPar : XML.Attribute;
s : String;
BEGIN
NEW(span); span.SetName("Span");
NEW(styleAttrPar); s := Strings.NewString("style"); styleAttrPar.SetName(s^);
styleAttrPar.SetValue(style);
span.AddAttribute(styleAttrPar);
RETURN span;
END GetNewSpan;
PROCEDURE FindProcedure(name : ARRAY OF CHAR) : TransformProc;
VAR
transformProc : TransformProc;
moduleName, procedureName : Modules.Name; msg : ARRAY 32 OF CHAR; res : LONGINT;
cur : XMLPluginProcInfo;
BEGIN {EXCLUSIVE}
Strings.Delete(name, 0, 3);
cur := xmlPluginProcs;
WHILE cur # NIL DO
IF cur.name = name THEN
Commands.Split(cur.procedure, moduleName, procedureName, res, msg);
IF (res = Commands.Ok) THEN
GETPROCEDURE(moduleName, procedureName, transformProc);
RETURN transformProc;
END;
END;
cur := cur.next
END;
RETURN NIL
END FindProcedure;
PROCEDURE Register*(context : Commands.Context);
VAR c : XMLPluginProcInfo;
BEGIN {EXCLUSIVE}
NEW(c);
context.arg.SkipWhitespace; context.arg.String(c.name);
context.arg.SkipWhitespace; context.arg.String(c.procedure);
c.next := xmlPluginProcs; xmlPluginProcs := c;
StoreXMLPlugins;
END Register;
PROCEDURE StoreXMLPlugins;
VAR f : Files.File;
w : Files.Writer;
cur : XMLPluginProcInfo;
res : LONGINT;
n0, n1 : ARRAY 64 OF CHAR;
BEGIN
n0 := "XMLPluginConfig.dat"; n1 := "XMLPluginConfig.dat.Bak";
Files.Rename(n0, n1, res);
f := Files.New("XMLPluginConfig.dat");
Files.OpenWriter(w, f, 0);
Files.Register(f);
cur := xmlPluginProcs;
WHILE cur # NIL DO
w.Char('"'); w.String(cur.name); w.Char('"'); w.Char(09X);
w.Char('"'); w.String(cur.procedure); w.Char('"'); w.Ln;
cur := cur.next
END;
w.Update
END StoreXMLPlugins;
PROCEDURE LoadXMLPlugins;
VAR f : Files.File;
r : Files.Reader;
c : XMLPluginProcInfo;
BEGIN
f := Files.Old("XMLPluginConfig.dat");
IF f # NIL THEN
Files.OpenReader(r, f, 0);
WHILE r.res = 0 DO
NEW(c);
r.String(c.name); r.SkipWhitespace;
r.String(c.procedure);
IF r.res = 0 THEN c.next := xmlPluginProcs; xmlPluginProcs:= c END;
r.SkipLn
END
END
END LoadXMLPlugins;
BEGIN
LoadXMLPlugins;
END XMLTransformer.