[Adapdev-commits] Adapdev/src/Adapdev.NVelocity/Dvsl Dvsl.cs,1.4,1.5 DvslContext.cs,1.4,1.5 DvslNode
Status: Beta
Brought to you by:
intesar66
Update of /cvsroot/adapdev/Adapdev/src/Adapdev.NVelocity/Dvsl In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv909/src/Adapdev.NVelocity/Dvsl Added Files: Dvsl.cs DvslContext.cs DvslNode.cs DvslNodeContext.cs DvslNodeImpl.cs TransformTool.cs Transformer.cs Log Message: --- NEW FILE: Transformer.cs --- namespace NVelocity.Dvsl { using System; using System.Collections; using System.IO; using System.Xml; using NVelocity.App; using NVelocity.Context; /// <summary> <p> /// Class responsible for actual transformation /// of documents. /// </p> /// <p> /// Note that this class is <em>not</em> threadsafe. /// </p> /// </summary> /// <author> <a href="mailto:ge...@ap...">Geir Magnusson Jr.</a></author> internal class Transformer : TransformTool { /// <summary> /// Instance of VelocityEngine we are currently using. /// This must be reset with a stylesheeet change /// </summary> private VelocityEngine ve = null; /// <summary> /// basic context passed to us - can contain tools /// and such for use. Is protected from change via /// wrapping /// </summary> private IContext baseContext; /// <summary> /// context used during processing. Wraps the baseContext /// </summary> private DVSLNodeContext currentContext; private TemplateHandler templateHandler = null; /// <summary> /// HashMap to hold application values /// </summary> private Hashtable appValue = new Hashtable(); /// <summary> /// Sole public CTOR. We rely on the caller to give us a /// VelocityEngine ready with all macros registered. /// The context is the callers context with all tools and /// style drek. /// </summary> public Transformer(VelocityEngine ve, TemplateHandler th, IContext context, Hashtable applicationValues, bool validate) { this.ve = ve; this.baseContext = context; this.templateHandler = th; appValue = applicationValues; } /// <summary> /// Method that performs the transformation on /// a document /// </summary> /// <param name="reader">XML document char stream</param> /// <param name="writer">Writer to output transformation to</param> internal virtual long Transform(TextReader reader, TextWriter writer) { /* * parse the document */ XmlDocument document = new XmlDocument(); document.Load(reader); return Transform(document, writer); } internal virtual long Transform(XmlDocument dom4jdoc, TextWriter writer) { /* * wrap the document. We do this as we let the dom4j package * decide if we have a match against "/", so we need document * to do that */ DvslNode root = new DvslNodeImpl(dom4jdoc); return Transform(root, writer); } protected internal virtual long Transform(DvslNode root, TextWriter writer) { /* * wrap in a context to keep subsequent documents from * interacting with each other */ currentContext = new DVSLNodeContext(baseContext); long start = (DateTime.Now.Ticks - 621355968000000000)/10000; /* * push 'this' into the context as our TransformTool * and invoke the transformation */ currentContext.Put("context", this); Invoke(root, writer); long end = (DateTime.Now.Ticks - 621355968000000000)/10000; return end - start; } private void Invoke(DvslNode element, TextWriter writer) { String[] arr = new String[] {}; currentContext.PushNode(element); templateHandler.Render(element, currentContext, writer); currentContext.PopNode(); } public virtual Object Get(String key) { return currentContext.Get(key); } public virtual String ApplyTemplates(DvslNode node, String xpath) { /* * get the nodes that was asked for */ IList nodeset = node.SelectNodes(xpath); StringWriter sw = new StringWriter(); for (int i = 0; i < nodeset.Count; i++) { DvslNode n = (DvslNode) nodeset[i]; Invoke(n, sw); } return sw.ToString(); } public virtual String ApplyTemplates(DvslNode node) { StringWriter sw = new StringWriter(); Invoke(node, sw); return sw.ToString(); } public virtual String ApplyTemplates() { return ApplyTemplates(currentContext.PeekNode(), "*|@*|text()|comment()|processing-instruction()"); } public virtual String ApplyTemplates(String path) { DvslNode node = currentContext.PeekNode(); return ApplyTemplates(node, path); } public virtual String Copy() { /* * fakie, for now */ DvslNode node = currentContext.PeekNode(); return node.Copy(); } public virtual Object GetAppValue(Object key) { return appValue[key]; } public virtual Object PutAppValue(Object key, Object value) { return appValue[key] = value; } } } --- NEW FILE: DvslNodeContext.cs --- namespace NVelocity.Dvsl { using System; using System.Collections; using NVelocity.Context; /// <summary> <p> /// Context implementation that is the outer context /// during the transformation. Holds the node stack /// and also protects the 'special' context elements /// like 'node' /// </p> /// <p> /// There are special elements like 'node', which is /// readonly and corresponds to the current node, and /// 'attrib', which corresponds to a map of attributes /// for the current node. /// </p> /// </summary> /// <author> <a href="mailto:ge...@ap...">Geir Magnusson Jr.</a></author> internal class DVSLNodeContext : VelocityContext { /// <summary> /// Magic context entity that corresponds /// to the current node /// </summary> private const String NODE = "node"; /// <summary> /// Magic context entity that corresponds to /// a Map of attributes for the current node /// </summary> private const String ATTRIB = "attrib"; /// <summary> /// Used to hold the nodes as we get invoked from /// within the document for applyTemplates() duties /// </summary> private Stack nodeStack = new Stack(); protected internal Hashtable ctx = new Hashtable(); public DVSLNodeContext(IContext context) : base(context) { } public DVSLNodeContext() { } /// <summary> /// retrieves value for key from internal storage /// </summary> /// <param name="key">name of value to get</param> /// <returns>value as object</returns> public override Object InternalGet(String key) { Object o = null; /* * special token : NODE * * returns current node */ if (key.Equals(NODE)) { return PeekNode(); } /* * ATTRIB - returns attribute map */ if (key.Equals(ATTRIB)) { DvslNode n = PeekNode(); return n.AttribMap; } /* * start with local storage */ return ctx[key]; } /// <summary> /// stores the value for key to internal /// storage /// </summary> /// <param name="key">name of value to store /// </param> /// <param name="value">value to store /// </param> /// <returns>previous value of key as Object /// </returns> public override Object InternalPut(String key, Object value) { /* * protect both NODE and ATTRIB for now. We * might want to let people set ATTRIB, but * I suspect not */ if (key.Equals(NODE)) return null; if (key.Equals(ATTRIB)) return null; return ctx[key] = value; } /// <summary> /// determines if there is a value for the /// given key /// </summary> /// <param name="key">name of value to check /// </param> /// <returns>true if non-null value in store /// </returns> public override bool InternalContainsKey(Object key) { return ctx.ContainsKey(key); } /// <summary> /// returns array of keys /// $$$ GMJ todo /// </summary> /// <returns>keys as [] /// </returns> public override Object[] InternalGetKeys() { return null; } /// <summary> /// remove a key/value pair from the internal storage /// </summary> /// <param name="key">name of value to remove</param> /// <returns>value removed</returns> public override Object InternalRemove(Object key) { Object o = ctx[key]; ctx.Remove(key); return o; } /* === routines to manage current node stack === */ internal virtual DvslNode PushNode(DvslNode n) { nodeStack.Push(n); return n; } internal virtual DvslNode PeekNode() { return (DvslNode) nodeStack.Peek(); } internal virtual DvslNode PopNode() { return (DvslNode) nodeStack.Pop(); } internal virtual void ClearNode() { nodeStack.Clear(); return; } } } --- NEW FILE: DvslContext.cs --- namespace NVelocity.Dvsl { using System; using System.Collections; using NVelocity.Context; /// <summary> /// Context implementation that handles wrapping several /// contexts simultaneously. The style context gets /// special treatment, getting checked first. /// </summary> /// <author> <a href="mailto:ge...@ap...">Geir Magnusson Jr.</a></author> internal class DvslContext : VelocityContext { protected internal IContext styleContext = null; protected internal IList contextList = new ArrayList(); /// <summary> /// Used to hold the nodes as we get invoked from /// within the document for applyTemplates() duties /// </summary> private Stack nodeStack = new Stack(); protected internal Hashtable ctx = new Hashtable(); public DvslContext() { } public virtual DvslNode PushNode(DvslNode n) { nodeStack.Push(n); return n; } public virtual DvslNode PeekNode() { return (DvslNode) nodeStack.Peek(); } public virtual DvslNode PopNode() { return (DvslNode) nodeStack.Pop(); } public virtual void ClearNode() { nodeStack.Clear(); return; } public virtual void ClearContexts() { styleContext = null; contextList.Clear(); } public virtual void AddContext(IContext c) { if (c != null) contextList.Add(c); } /// <summary> /// retrieves value for key from internal storage /// </summary> /// <param name="key">name of value to get</param> /// <returns>value as object</returns> public override Object InternalGet(String key) { Object o = null; /* * special tokens */ if (key.Equals("node")) { return PeekNode(); } /* * start with local storage */ o = ctx[key]; if (o != null) return o; /* * if that doesn't work, try style first * then others */ if (styleContext != null) { o = styleContext.Get(key); if (o != null) return o; } for (int i = 0; i < contextList.Count; i++) { IContext c = (IContext) contextList[i]; o = c.Get(key); if (o != null) return o; } return null; } /// <summary> /// stores the value for key to internal storage /// </summary> /// <param name="key">name of value to store</param> /// <param name="value">value to store</param> /// <returns>previous value of key as Object</returns> public override Object InternalPut(String key, Object value) { if (key.Equals("node")) return null; return ctx[key] = value; } /// <summary> /// determines if there is a value for the given key /// </summary> /// <param name="key">name of value to check</param> /// <returns>true if non-null value in store</returns> public override bool InternalContainsKey(Object key) { /* * start with local storage */ if (ctx.ContainsKey(key)) return true; /* * if that doesn't work, try style first * then others */ if (styleContext != null && styleContext.ContainsKey(key)) return true; for (int i = 0; i < contextList.Count; i++) { IContext c = (IContext) contextList[i]; if (c.ContainsKey(key)) return true; } return false; } /// <summary> /// returns array of keys /// /// $$$ GMJ todo /// /// </summary> /// <returns>keys as []</returns> public override Object[] InternalGetKeys() { return null; } /// <summary> /// remove a key/value pair from the /// internal storage /// </summary> /// <param name="key">name of value to remove</param> /// <returns>value removed</returns> public override Object InternalRemove(Object key) { Object o = ctx[key]; ctx.Remove(key); return o; } public virtual IContext StyleContext { set { styleContext = value; } } } } --- NEW FILE: TransformTool.cs --- namespace NVelocity.Dvsl { using System; /// <summary> /// This is the tool interface exposed to the stylesheet. /// </summary> /// <author> <a href="mailto:ge...@ap...">Geir Magnusson Jr.</a></author> public interface TransformTool { /// <summary> /// Applies templates in the current stylesheet /// to the nodeset returned by the XPath expression /// </summary> /// <param name="xpath">XPath expression to select nodes</param> /// <returns>The rendered result</returns> String ApplyTemplates(String xpath); String ApplyTemplates(DvslNode node); String ApplyTemplates(DvslNode node, String xpath); String ApplyTemplates(); String Copy(); Object Get(String key); Object GetAppValue(Object key); Object PutAppValue(Object key, Object value); } } --- NEW FILE: Dvsl.cs --- namespace NVelocity.Dvsl { using System; using System.Collections; using System.IO; using System.Xml; using Commons.Collections; using NVelocity.App; using NVelocity.Context; using NVelocity.Runtime; /// <summary> /// Main DVSL class - use this as the helper class for apps /// </summary> /// <author> <a href="mailto:ge...@ap...">Geir Magnusson Jr.</a></author> /// <author> <a href="mailto:bi...@pr...">Bill Burton.</a></author> public class Dvsl { private static String TOOL_PROP_PREFIX = "toolbox.tool."; private static String STRING_PROP_PREFIX = "toolbox.string."; private static String INTEGER_PROP_PREFIX = "toolbox.integer."; private static String TOOLBOX_NAME = "toolbox.contextname."; private VelocityEngine ve = null; private XmlDocument currentDocument = null; private StreamWriter currentWriter = null; private IContext toolContext; private IContext userContext; private IContext styleContext; private DvslContext baseContext = new DvslContext(); private Transformer transformer; private bool ready = false; private Hashtable velConfig = null; private FileInfo logFile; private Hashtable appVals = new Hashtable(); private TemplateHandler templateHandler = new TemplateHandler(); internal bool validate = false; /// <summary> /// lets the user specify a filename for logging. /// </summary> public virtual FileInfo LogFile { set { this.logFile = value; if (velConfig == null) { velConfig = new Hashtable(); } velConfig[RuntimeConstants_Fields.RUNTIME_LOG] = value.FullName; } } /// <summary> /// lets the user pass a java.util.Properties containing /// properties for the configuration of the VelocityEngine /// used by DVSL /// </summary> public virtual Hashtable VelocityConfig { set { if (velConfig != null) { foreach (Object key in velConfig.Keys) { value.Add(key, velConfig[key]); } } velConfig = value; } } /// <summary> /// Sets the user context. The user context is /// a Velocity Context containing user-supplied /// objects and data that are to be made available /// in the template /// </summary> /// <param name="ctx">User context of data</param> public virtual IContext UserContext { set { ready = false; userContext = value; } } /// <summary> /// Uses a validating parser on all input documents /// </summary> /// <param name="">validate</param> public virtual bool ValidatingParser { set { validate = value; } } /// <summary> /// <p>Loads the toolbox from the input Properties.</p> /// <p>Currently supports specification of the Toolbox /// name in the context, creating classes, and string /// and integer values. Ex : /// </p> /// /// <pre> /// toolbox.contextname = floyd /// toolbox.tool.footool = Footool /// toolbox.string.mystring = Hello there! /// toolbox.integer.myint = 7 /// toolbox.string.sourcebase = ./xdocs/ /// </pre> /// /// <p> /// So in template, this toolbox and it's values would /// be accessed as : /// </p> /// <pre> /// $context.floyd.footool.getFoo() /// $context.floyd.mystring /// $context.floyd.myint /// </pre> /// </summary> public virtual ExtendedProperties Toolbox { set { ready = false; /* * for each key that looks like * toolbox.tool.<token> = class */ Hashtable toolbox = new Hashtable(); String toolboxname = "toolbox"; IEnumerator it = value.Keys; while (it.MoveNext()) { String key = it.Current.ToString(); String val = value.GetString(key); if (key.StartsWith(TOOL_PROP_PREFIX)) { String toolname = key.Substring(TOOL_PROP_PREFIX.Length); Type type = Type.GetType(val); Object o = Activator.CreateInstance(type); toolbox[toolname] = o; } else if (key.StartsWith(INTEGER_PROP_PREFIX)) { String toolname = key.Substring(INTEGER_PROP_PREFIX.Length); int i = 0; try { i = Int32.Parse(val); } catch (Exception ee) { } toolbox[toolname] = i; } else if (key.StartsWith(STRING_PROP_PREFIX)) { String toolname = key.Substring(STRING_PROP_PREFIX.Length); toolbox[toolname] = val; } else if (key.StartsWith(TOOLBOX_NAME)) { toolboxname = val; } } toolContext = new VelocityContext(); toolContext.Put(toolboxname, toolbox); } } /// <summary> /// Convenience function. See... /// </summary> public virtual void SetStylesheet(String value) { SetStylesheet(new FileInfo(value)); } /// <summary> /// Convenience function. See... /// </summary> public virtual void SetStylesheet(FileInfo value) { StreamReader fr = null; try { fr = new StreamReader(value.FullName); SetStylesheet(fr); } catch (Exception e) { throw; } finally { if (fr != null) { fr.Close(); } } } /// <summary> /// <p> /// Sets the stylesheet for this transformation set /// </p> /// /// <p> /// Note that don't need this for each document you want /// to transform. Just do it once, and transform away... /// </p> /// </summary> /// <param name="styleReader">Reader with stylesheet char stream</param> public virtual void SetStylesheet(TextReader value) { ready = false; /* * now initialize Velocity - we need to do that * on change of stylesheet */ ve = new VelocityEngine(); /* * if there are user properties, set those first - carefully */ if (velConfig != null) { ConfigureVelocityEngine(ve, velConfig); } /* * register our template() directive */ ve.SetProperty("userdirective", "NVelocity.Dvsl.Directive.MatchDirective;NVelocity"); ve.Init(); /* * add our template accumulator */ ve.SetApplicationAttribute("NVelocity.Dvsl.TemplateHandler", templateHandler); /* * load and render the stylesheet * * this sets stylesheet specific context * values */ StringWriter junkWriter = new StringWriter(); styleContext = new VelocityContext(); ve.Evaluate(styleContext, junkWriter, "DVSL:stylesheet", value); /* * now run the base template through for the rules */ // TODO - use ResourceLocator or something else - I don't like the path to the resource Stream s = this.GetType().Assembly.GetManifestResourceStream("NVelocity.Dvsl.Resource.defaultroot.dvsl"); if (s == null) { Console.Out.WriteLine("DEFAULT TRANSFORM RULES NOT FOUND "); } else { ve.Evaluate(new VelocityContext(), junkWriter, "defaultroot.dvsl", new StreamReader(s)); s.Close(); } /* * need a new transformer, as it depends on the * velocity engine */ transformer = new Transformer(ve, templateHandler, baseContext, appVals, validate); } /// <summary> /// <p> /// Add mapped properties from hashtable on VelocityEngine. /// </p> /// <p> /// If you are going to use this, ensure you do it *before* setting /// the stylesheet, as that creates the VelocityEngine /// </p> /// </summary> private void ConfigureVelocityEngine(VelocityEngine ve, Hashtable map) { if (ve == null || map == null) { return; } foreach (DictionaryEntry entry in map) { ve.SetProperty((String) entry.Key, entry.Value); } } /// <summary> /// sets up all the context goodies /// </summary> protected internal virtual void MakeReady() { /* * put all the contexts together */ baseContext.ClearContexts(); baseContext.AddContext(userContext); baseContext.AddContext(toolContext); baseContext.StyleContext = styleContext; ready = true; } /// <summary> /// does the transformation of the inputstream into /// the output writer /// </summary> protected internal virtual long XForm(TextReader reader, TextWriter writer) { if (!ready) { MakeReady(); } return transformer.Transform(reader, writer); } protected internal virtual long XForm(XmlDocument dom4jdoc, TextWriter writer) { if (!ready) { MakeReady(); } return transformer.Transform(dom4jdoc, writer); } public virtual long Transform(FileInfo f, TextWriter writer) { StreamReader reader = null; try { reader = new StreamReader(f.FullName); return XForm(reader, writer); } catch (Exception e) { throw e; } finally { if (reader != null) { reader.Close(); } } } public virtual long Transform(TextReader reader, TextWriter writer) { return XForm(reader, writer); } public virtual long Transform(Stream stream, TextWriter writer) { return XForm(new StreamReader(stream), writer); } /// <summary> /// Transforms the given dom4j Document into the writer. /// </summary> /// <param name="dom4jdoc">dom4j Document object</param> /// <param name="writer">Writer for output</param> public virtual long Transform(XmlDocument dom4jdoc, TextWriter writer) { return XForm(dom4jdoc, writer); } public virtual long Transform(String infile, TextWriter writer) { StreamReader reader = null; try { reader = new StreamReader(infile); return XForm(reader, writer); } catch (Exception e) { throw e; } finally { if (reader != null) { reader.Close(); } } } /// <summary> /// Gets the application value for the specified key /// </summary> /// <param name="key">key to use to retrieve value</param> /// <returns>value if found, null otherwise</returns> public virtual Object GetAppValue(Object key) { return appVals[key]; } /// <summary> /// Sets the application value for the specified key /// </summary> /// <param name="key">key to use to store value</param> /// <param name="value">value to be stored</param> /// <returns>old value if any, null otherwise</returns> public virtual Object PutAppValue(Object key, Object value) { return appVals[key] = value; } /// <summary> /// <p> /// Allows command-line access. /// </p> /// <p> /// Usage : Dvsl.exe -STYLE stylesheeet [-IN infile] [-OUT outfile] [-TOOL toolboxname] /// </p> /// </summary> [STAThread] public static void Main(String[] args) { Dvsl dvsl = new Dvsl(); TextReader reader = Console.In; String infile = null; String style = null; String outfile = null; TextWriter writer = Console.Out; String toolfile = null; for (int i = 0; i < args.Length; i++) { if (args[i].Equals("-IN")) infile = args[++i]; else if (args[i].Equals("-OUT")) outfile = args[++i]; else if (args[i].Equals("-STYLE")) style = args[++i]; else if (args[i].Equals("-TOOL")) toolfile = args[++i]; } if (style == null) { Console.Out.WriteLine("usage :need to specify a stylesheet. "); Console.Out.WriteLine("Dvsl.exe -STYLE stylesheeet [-IN infile] [-OUT outfile] [-TOOL toolboxname]"); return; } if (style != null) dvsl.SetStylesheet(style); if (toolfile != null) { ExtendedProperties p = new ExtendedProperties(); Stream fis = new FileStream(toolfile, FileMode.Open, FileAccess.Read); p.Load(fis); dvsl.Toolbox = p; } if (infile != null) reader = new StreamReader(infile); if (outfile != null) writer = new StreamWriter(outfile); long time = dvsl.Transform(reader, writer); writer.Flush(); } } } --- NEW FILE: DvslNodeImpl.cs --- namespace NVelocity.Dvsl { using System; using System.Collections; using System.IO; using System.Xml; /// <summary> /// wrapper class for .Net nodes to implement the /// DVSLNode interface for template use /// </summary> /// <author> <a href="mailto:ge...@ap...">Geir Magnusson Jr.</a></author> public class DvslNodeImpl : DvslNode { protected internal XmlNode element = null; protected internal Hashtable attributes = null; /// <summary> /// this is a bit yecchy - need to revamp /// </summary> public DvslNodeImpl(XmlElement e) { element = e; } public DvslNodeImpl(XmlDocument e) { element = e; } public DvslNodeImpl(XmlText e) { element = e; } public DvslNodeImpl(XmlAttribute e) { element = e; } public DvslNodeImpl(XmlComment e) { element = e; } public DvslNodeImpl(XmlCDataSection e) { element = e; } public DvslNodeImpl() { } public virtual Object NodeImpl { get { return element; } } public virtual Hashtable AttribMap { get { /* * $$$ GMJ sync issue? yes. Do I care? */ if (attributes == null) { attributes = new Hashtable(); } /* * only Elements have attributes */ if (element is XmlElement) { XmlElement e = (XmlElement) element; foreach (XmlAttribute at in e.Attributes) { attributes[at.Name] = at.Value; } } return attributes; } } /// <summary> /// returns the name of the node /// </summary> public virtual String Name { get { return element.Name; } } /// <summary> /// returns a specificed attributeattribute /// </summary> public virtual String Attribute(String attribute) { if (element is XmlElement) { return ((XmlElement) element).Attributes[attribute].Value; } return null; } /// <summary> /// returns a list of nodes that satisfy the xpath /// </summary> public virtual IList SelectNodes(String xpath) { XmlNodeList l = element.SelectNodes(xpath); IList list = new ArrayList(); for (int i = 0; i < l.Count; i++) { XmlNode n = l[i]; if (n != null) { DvslNode dn = MakeDvslNode(n); if (dn != null) { list.Add(dn); } } } return list; } public virtual DvslNode SelectSingleNode(String xpath) { XmlNode n = element.SelectSingleNode(xpath); return MakeDvslNode(n); } public virtual DvslNode Get(String xpath) { return SelectSingleNode(xpath); } public virtual String Value { get { return element.InnerText; } } public virtual Object ValueOf(String xpath) { Object o = element.CreateNavigator().Evaluate(xpath); return o; } public override String ToString() { return Value; } public virtual IList Children() { IList list = new ArrayList(); if (element.NodeType == XmlNodeType.Element) { XmlNodeList nodes = ((XmlElement) element).ChildNodes; for (int i = 0; i < nodes.Count; i++) list.Add(MakeDvslNode(nodes[i])); } return list; } /// <summary> /// assumes a list of DVSLNodes /// </summary> public virtual String Copy(IList nodes) { if (nodes == null) return ""; StringWriter sw = new StringWriter(); for (int i = 0; i < nodes.Count; i++) { DvslNode dn = (DvslNode) nodes[i]; sw.Write(((XmlNode) dn.NodeImpl).OuterXml); } return sw.ToString(); } public virtual String Copy() { return element.OuterXml; } public virtual String Render() { try { StringWriter sw = new StringWriter(); XmlTextWriter tw = new XmlTextWriter(sw); element.WriteContentTo(tw); return tw.ToString(); } catch (Exception e) { } return ""; } public virtual String Attrib(String name) { if (element is XmlElement) { XmlAttribute attrib = ((XmlElement) element).Attributes[name]; if (attrib != null) { return attrib.Value; } } return null; } /// <summary> /// will recast all of this later /// </summary> private DvslNode MakeDvslNode(XmlNode n) { if (n == null) { return null; } if (n.NodeType == XmlNodeType.Element) { return new DvslNodeImpl((XmlElement) n); } else if (n.NodeType == XmlNodeType.Text) { return new DvslNodeImpl((XmlText) n); } else if (n.NodeType == XmlNodeType.Attribute) { return new DvslNodeImpl((XmlAttribute) n); } else if (n.NodeType == XmlNodeType.Comment) { return new DvslNodeImpl((XmlComment) n); } else if (n.NodeType == XmlNodeType.CDATA) { return new DvslNodeImpl((XmlCDataSection) n); } else if (n.NodeType == XmlNodeType.ProcessingInstruction) { // not a supported node type return null; } //TODO: log the unknown node type so that it can be determined is something is missing return null; } } } --- NEW FILE: DvslNode.cs --- namespace NVelocity.Dvsl { using System; using System.Collections; /// <summary> /// wrapper interface for nodes exposed in the /// template. Isolates the in-VSL DOM from that /// of the underlying implementation /// </summary> /// <author> <a href="mailto:ge...@ap...">Geir Magnusson Jr.</a></author> public interface DvslNode { /// <summary> /// returns the name of the node /// </summary> String Name { get; } /// <summary> /// returns the 'value' of the node /// </summary> String Value { get; } /// <summary> /// returns the value of the XPath /// expression /// </summary> Object ValueOf(String xpath); /// <summary> /// returns attribute /// </summary> String Attrib(String attribute); /// <summary> /// returns a list of nodes that satisfy /// the xpath /// </summary> IList SelectNodes(String xpath); /// <summary> returns a single node that satisfies /// the xpath /// </summary> DvslNode SelectSingleNode(String xpath); DvslNode Get(String xpath); /// <summary> /// renders a deep copy of the XML tree /// below the current node to the output /// </summary> String Copy(); /// <summary> /// renders a deep copy of the nodes in /// the list ot the output /// </summary> String Copy(IList nodeList); /// <summary> /// returns a list of all children of the current node /// </summary> IList Children(); /// <summary> /// returns the 'value' of the node /// </summary> String ToString(); /// <summary> /// returns the object corresponding to the node /// in the implementaion that we are using. /// use only with the greatest of care /// </summary> Object NodeImpl { get; } Hashtable AttribMap { get; } } } |