示例#1
0
 public override string Evaluate(RequestProcess process)
 {
     try {
         if (process.Bot.SraixServices.TryGetValue(this.ServiceName, out var service))
         {
             var text = this.Children?.Evaluate(process) ?? "";
             process.Log(LogLevel.Diagnostic, "In element <sraix>: querying service '" + this.ServiceName + "' to process text '" + text + "'.");
             text = service.Process(text, this.Attributes, process);
             process.Log(LogLevel.Diagnostic, "In element <sraix>: the request returned '" + text + "'.");
             return(text);
         }
         else
         {
             process.User.Predicates["SraixException"]        = nameof(KeyNotFoundException);
             process.User.Predicates["SraixExceptionMessage"] = "No service named '" + this.ServiceName + "' is known.";
             process.Log(LogLevel.Warning, "In element <sraix>: no service named '" + this.ServiceName + "' is known.");
             return((this.DefaultReply ?? new TemplateElementCollection(new Srai(new TemplateElementCollection("SRAIXFAILED")))).Evaluate(process));
         }
     } catch (Exception ex) {
         process.User.Predicates["SraixException"]        = ex.GetType().Name;
         process.User.Predicates["SraixExceptionMessage"] = ex.Message;
         process.Log(LogLevel.Warning, "In element <sraix>: service '" + this.ServiceName + "' threw " + ex.GetType().Name + ":\n" + ex.ToString());
         return((this.DefaultReply ?? new TemplateElementCollection(new Srai(new TemplateElementCollection("SRAIXFAILED")))).Evaluate(process));
     }
 }
示例#2
0
            public override string Evaluate(RequestProcess process)
            {
                process.Log(LogLevel.Info, $"In element <test>: running test {this.Name}");
                string text = this.Children?.Evaluate(process) ?? "";

                process.Log(LogLevel.Diagnostic, "In element <test>: processing text '" + text + "'.");
                var newRequest = new Aiml.Request(text, process.User, process.Bot);

                text = process.Bot.ProcessRequest(newRequest, false, false, process.RecursionDepth + 1, out var duration).ToString().Trim();
                process.Log(LogLevel.Diagnostic, "In element <test>: the request returned '" + text + "'.");

                if (process.testResults != null)
                {
                    var        expectedResponse = this.ExpectedResponse.Evaluate(process).Trim();
                    TestResult result;
                    if (process.Bot.Config.CaseSensitiveStringComparer.Equals(text, expectedResponse))
                    {
                        result = TestResult.Pass(duration);
                    }
                    else
                    {
                        result = TestResult.Failure($"Expected response: {expectedResponse}\nActual response: {text}", duration);
                    }
                    process.testResults[this.Name] = result;
                }
                else
                {
                    process.Log(LogLevel.Warning, "In element <test>: Tests are not being used.");
                }

                return(text);
            }
示例#3
0
            public override string Evaluate(RequestProcess process)
            {
                // Does the triple already exist?
                var clause = new Clause(this.Subject, this.Predicate, this.Object, true);

                clause.Evaluate(process);

                if (string.IsNullOrWhiteSpace(clause.subj) || string.IsNullOrWhiteSpace(clause.pred) || string.IsNullOrWhiteSpace(clause.obj))
                {
                    process.Log(LogLevel.Diagnostic, $"In element <addtriple>: Could not add triple with missing elements.  Subject: {clause.subj}  Predicate: {clause.pred}  Object: {clause.obj}");
                    return(process.Bot.Config.DefaultTriple);
                }

                var triples = process.Bot.Triples.Match(clause);

                if (triples.Count != 0)
                {
                    process.Log(LogLevel.Diagnostic, $"In element <addtriple>: Triple already exists at key {triples.First()}.  Subject: {clause.subj}  Predicate: {clause.pred}  Object: {clause.obj}");
                    return(triples.First().ToString());
                }

                // Add the triple.
                int key = process.Bot.Triples.Add(clause.subj, clause.pred, clause.obj);

                process.Log(LogLevel.Diagnostic, $"In element <addtriple>: Added a new triple with key {key}.  Subject: {clause.subj}  Predicate: {clause.pred}  Object: {clause.obj}");
                return(key.ToString());
            }
示例#4
0
            public override string Evaluate(RequestProcess process)
            {
                var clause = new Clause(this.Subject, this.Predicate, this.Object, true);

                clause.Evaluate(process);

                if (string.IsNullOrWhiteSpace(clause.subj) || string.IsNullOrWhiteSpace(clause.pred) || string.IsNullOrWhiteSpace(clause.obj))
                {
                    process.Log(LogLevel.Diagnostic, $"In element <deletetriple>: Could not delete triple with missing elements.  Subject: {clause.subj}  Predicate: {clause.pred}  Object: {clause.obj}");
                    return(process.Bot.Config.DefaultTriple);
                }

                var triples = process.Bot.Triples.Match(clause);

                if (triples.Count == 0)
                {
                    process.Log(LogLevel.Diagnostic, $"In element <deletetriple>: No such triple exists.  Subject: {clause.subj}  Predicate: {clause.pred}  Object: {clause.obj}");
                    return(process.Bot.Config.DefaultTriple);
                }

                var index = triples.Single();

                process.Bot.Triples.Remove(index);
                process.Log(LogLevel.Diagnostic, $"In element <deletetriple>: Deleted the triple with key {index}.  Subject: {clause.subj}  Predicate: {clause.pred}  Object: {clause.obj}");
                return(index.ToString());
            }
示例#5
0
文件: sr.cs 项目: xiaoxiongnpu/AIML-1
            public override string Evaluate(RequestProcess process)
            {
                string text = process.star[0];

                process.Log(LogLevel.Diagnostic, "In element <sr>: processing text '" + text + "'.");
                var newRequest = new Aiml.Request(text, process.User, process.Bot);

                text = process.Bot.ProcessRequest(newRequest, false, false, process.RecursionDepth + 1, out _).ToString();
                process.Log(LogLevel.Diagnostic, "In element <sr>: the request returned '" + text + "'.");
                return(text);
            }
示例#6
0
            public override string Evaluate(RequestProcess process)
            {
                // Evaluate the contents of clauses.
                foreach (var clause in this.Clauses)
                {
                    clause.Evaluate(process);
                }

                string[] visibleVars;
                if (this.Variables == null)
                {
                    visibleVars = new string[0];
                }
                else
                {
                    visibleVars = this.Variables.Evaluate(process).Split((char[])null, StringSplitOptions.RemoveEmptyEntries);
                }

                // Start with an empty tuple.
                Tuple tuple  = new Tuple(new HashSet <string>(visibleVars, process.Bot.Config.StringComparer));
                var   tuples = this.SelectFromRemainingClauses(process, tuple, 0);

                process.Log(LogLevel.Diagnostic, $"In element <select>: Found {tuples.Count} matching {(tuples.Count == 1 ? "tuple" : "tuples")}.");
                if (tuples.Count == 0)
                {
                    return(process.Bot.Config.DefaultTriple);
                }
                return(string.Join(" ", tuples.Select(t => t.Index)));
            }
示例#7
0
            public override string Evaluate(RequestProcess process)
            {
                StringBuilder builder = new StringBuilder();

                li item; int loops = 0;

                do
                {
                    ++loops;
                    if (loops > process.Bot.Config.LoopLimit)
                    {
                        process.Log(LogLevel.Warning, "Loop limit exceeded. User: "******"; path: \"" + process.Path + "\"");
                        throw new LoopLimitException();
                    }

                    item = this.Pick(process);
                    if (item == null)
                    {
                        return(string.Empty);
                    }
                    builder.Append(item.Children?.Evaluate(process));
                } while (item.Children != null && item.Children.Loop);

                return(builder.ToString());
            }
示例#8
0
        public Template?Search(RequestSentence sentence, RequestProcess process, string that, bool traceSearch)
        {
            if (process.RecursionDepth > sentence.Bot.Config.RecursionLimit)
            {
                sentence.Bot.Log(LogLevel.Warning, "Recursion limit exceeded. User: "******"; raw input: \"" + sentence.Request.Text + "\"");
                throw new RecursionLimitException();
            }

            // Generate the input path.
            var messageSplit = sentence.Text.Split((char[]?)null, StringSplitOptions.RemoveEmptyEntries);
            var thatSplit    = that.Split((char[]?)null, StringSplitOptions.RemoveEmptyEntries);
            var topicSplit   = sentence.Bot.Normalize(sentence.User.Topic).Split((char[]?)null, StringSplitOptions.RemoveEmptyEntries);

            var inputPath = new string[messageSplit.Length + thatSplit.Length + topicSplit.Length + 2];
            int i         = 0;

            messageSplit.CopyTo(inputPath, 0);
            i += messageSplit.Length;
            inputPath[i++] = "<that>";
            thatSplit.CopyTo(inputPath, i);
            i += thatSplit.Length;
            inputPath[i++] = "<topic>";
            topicSplit.CopyTo(inputPath, i);
            if (traceSearch)
            {
                process.Log(LogLevel.Diagnostic, "Normalized path: " + string.Join(" ", inputPath));
            }

            var result = this.Search(sentence, process, inputPath, 0, traceSearch, MatchState.Message);

            return(result);
        }
示例#9
0
            public override string Evaluate(RequestProcess process)
            {
                string command = this.Command.Evaluate(process);

                Process process2 = new Process();

                if (Environment.OSVersion.Platform < PlatformID.Unix)
                {
                    // Windows
                    process2.StartInfo = new ProcessStartInfo(Path.Combine(Environment.SystemDirectory, "cmd.exe"), "/Q /D /C \"" +
                                                              Regex.Replace(command, @"[/\\:*?""<>^]", "^$0") + "\"");
                    //    /C string   Carries out the command specified by string and then terminates.
                    //    /Q          Turns echo off.
                    //    /D          Disable execution of AutoRun commands from registry (see 'CMD /?').
                }
                else if (Environment.OSVersion.Platform == PlatformID.Unix)
                {
                    // UNIX
                    process2.StartInfo = new ProcessStartInfo(Path.Combine(Path.GetPathRoot(Environment.SystemDirectory), "bin", "sh"),
                                                              command.Replace(@"\", @"\\").Replace("\"", "\\\""));
                }
                process2.StartInfo.UseShellExecute        = false;
                process2.StartInfo.RedirectStandardOutput = true;
                process2.StartInfo.RedirectStandardError  = true;

                process.Log(LogLevel.Diagnostic, $"In element <system>: executing {process2.StartInfo.FileName} {process2.StartInfo.Arguments}");

                process2.Start();

                string output  = process2.StandardOutput.ReadToEnd();
                string output2 = process2.StandardError.ReadToEnd();

                process2.WaitForExit((int)process.Bot.Config.Timeout);

                if (!process2.HasExited)
                {
                    process.Log(LogLevel.Diagnostic, $"In element <system>: the process timed out.");
                }
                else if (process2.ExitCode != 0)
                {
                    process.Log(LogLevel.Diagnostic, $"In element <system>: the process exited with code {process2.ExitCode}.");
                }

                return(output);
            }
示例#10
0
        internal void WriteGossip(RequestProcess process, string message)
        {
            var e = new GossipEventArgs(message);

            this.OnGossip(e);
            if (e.Handled)
            {
                return;
            }
            process.Log(LogLevel.Gossip, "Gossip from " + process.User.ID + ": " + message);
        }
示例#11
0
            public override string Evaluate(RequestProcess process)
            {
                string key   = this.Key.Evaluate(process);
                string value = (this.Children?.Evaluate(process) ?? "").Trim();

                var dictionary = this.LocalVar ? process.Variables : process.User.Predicates;

                if (process.Bot.Config.UnbindPredicatesWithDefaultValue &&
                    value == (this.LocalVar ? process.Bot.Config.DefaultPredicate : process.Bot.Config.GetDefaultPredicate(key)))
                {
                    dictionary.Remove(key);
                    process.Log(LogLevel.Diagnostic, "In element <set>: Unbound " + (this.LocalVar ? "local variable" : "predicate") + " '" + key + "' with default value '" + value + "'.");
                }
                else
                {
                    dictionary[key] = value;
                    process.Log(LogLevel.Diagnostic, "In element <set>: Set " + (this.LocalVar ? "local variable" : "predicate") + " '" + key + "' to '" + value + "'.");
                }

                return(value);
            }
示例#12
0
            public override string Evaluate(RequestProcess process)
            {
                this.Clause.Evaluate(process);

                // Find triples that match.
                var triples = process.Bot.Triples.Match(this.Clause);

                if (triples.Count == 0)
                {
                    process.Log(LogLevel.Diagnostic, $"In element <uniq>: No matching triple exists.  Subject: {this.Clause.subj}  Predicate: {this.Clause.pred}  Object: {this.Clause.obj}");
                    return(process.Bot.Config.DefaultTriple);
                }
                else if (triples.Count > 1)
                {
                    process.Log(LogLevel.Diagnostic, $"In element <uniq>: Found {triples.Count} matching triples.  Subject: {this.Clause.subj}  Predicate: {this.Clause.pred}  Object: {this.Clause.obj}");
                }

                var tripleIndex = triples.First();
                var triple      = process.Bot.Triples[tripleIndex];

                process.Log(LogLevel.Diagnostic, $"In element <uniq>: Found triple {tripleIndex}.  Subject: {triple.Subject}  Predicate: {triple.Predicate}  Object: {triple.Object}");

                // Get the result.
                if (this.Clause.obj.StartsWith("?"))
                {
                    return(triple.Object);
                }
                if (this.Clause.pred.StartsWith("?"))
                {
                    return(triple.Predicate);
                }
                if (this.Clause.subj.StartsWith("?"))
                {
                    return(triple.Subject);
                }
                process.Log(LogLevel.Warning, $"In element <uniq>: The clause contains no variables.  Subject: {this.Clause.subj}  Predicate: {this.Clause.pred}  Object: {this.Clause.obj}");
                return(process.Bot.Config.DefaultTriple);
            }
示例#13
0
            public override string Evaluate(RequestProcess process)
            {
                // Evaluate <eval> tags.
                XmlNode node = this.Node.Clone();

                this.ProcessXml(node, process);

                // Learn the result.
                process.Log(LogLevel.Diagnostic, $"In element <learn>: learning new category for {process.User.ID}: {node.OuterXml}");
                AimlLoader loader = new AimlLoader(process.Bot);

                loader.ProcessCategory(process.User.Graphmaster, node, null);

                return(string.Empty);
            }
示例#14
0
            public override string Evaluate(RequestProcess process)
            {
                // Evaluate <eval> tags.
                XmlNode node = this.Node.Clone();

                this.ProcessXml(node, process);

                // Learn the result.
                process.Log(LogLevel.Diagnostic, "In element <learnf>: learning new category: " + node.OuterXml);
                AimlLoader loader = new AimlLoader(process.Bot);

                loader.ProcessCategory(process.Bot.Graphmaster, node, null);

                // Write it to a file.
                bool         newFile = !File.Exists(process.Bot.Config.LearnfFile) || new FileInfo(process.Bot.Config.LearnfFile).Length < 7;
                StreamWriter writer  = new StreamWriter(File.Open("learnf.aiml", FileMode.OpenOrCreate, FileAccess.Write));

                if (newFile)
                {
                    writer.WriteLine("<!-- This file contains AIML categories the bot has learned via <learnf> elements. -->");
                    writer.WriteLine();
                    writer.WriteLine("<aiml version=\"2.0\">");
                    writer.WriteLine();
                }
                else
                {
                    // Seek to just before the closing </aiml> tag.
                    writer.BaseStream.Seek(-7, SeekOrigin.End);
                }

                writer.WriteLine("<!-- Learned from " + process.User.ID + " via category '" + process.Path + "' on " + DateTime.Now + ". -->");
                writer.Write(node.InnerXml.Trim('\r', '\n'));
                writer.WriteLine();
                writer.WriteLine();
                writer.Write("</aiml>");
                writer.Close();

                return(string.Empty);
            }
示例#15
0
            public li?Pick(RequestProcess process)
            {
                string value;

                foreach (var item in this.items)
                {
                    string?key        = item.Key?.Evaluate(process);
                    string?checkValue = item.Value?.Evaluate(process);

                    Dictionary <string, string> dictionary;
                    if (item.LocalVar)
                    {
                        dictionary = process.Variables;
                    }
                    else
                    {
                        dictionary = process.User.Predicates;
                    }

                    if (key != null && checkValue != null)
                    {
                        if (checkValue == "*")
                        {
                            // '*' is a match if the predicate is bound at all.
                            if (item.LocalVar)
                            {
                                if (process.Variables.TryGetValue(key, out value))
                                {
                                    process.Log(LogLevel.Diagnostic, $"In element <condition>: Local variable {key} matches *.");
                                    return(item);
                                }
                            }
                            else
                            {
                                if (process.User.Predicates.TryGetValue(key, out value))
                                {
                                    process.Log(LogLevel.Diagnostic, $"In element <condition>: Local variable {key} matches *.");
                                    return(item);
                                }
                            }
                        }
                        else
                        {
                            if (item.LocalVar)
                            {
                                if (process.Bot.Config.StringComparer.Equals(process.GetVariable(key), checkValue))
                                {
                                    process.Log(LogLevel.Diagnostic, $"In element <condition>: Local variable {key} matches {checkValue}.");
                                    return(item);
                                }
                            }
                            else
                            {
                                if (process.Bot.Config.StringComparer.Equals(checkValue, process.User.GetPredicate(key)))
                                {
                                    process.Log(LogLevel.Diagnostic, $"In element <condition>: {(item.LocalVar ? "Local variable" : "Predicate")} {key} matches {checkValue}.");
                                    return(item);
                                }
                            }
                        }
                        // No match; keep looking.
                        process.Log(LogLevel.Diagnostic, $"In element <condition>: {(item.LocalVar ? "Local variable" : "Predicate")} {key} does not match {checkValue}.");
                    }
                    else if (key == null && checkValue == null)
                    {
                        // Default case.
                        return(item);
                    }
                    else
                    {
                        process.Log(LogLevel.Warning, "In element <condition>: Missing name, var or value attribute in <li>.");
                    }
                }

                return(null);
            }
示例#16
0
            public override string Evaluate(RequestProcess process)
            {
                string format = null;

                if (this.Format != null)
                {
                    format = this.Format.Evaluate(process);
                }
                string jformat = null;

                if (this.JFormat != null)
                {
                    jformat = this.JFormat.Evaluate(process);
                }
                string localeString = null;

                if (this.Locale != null)
                {
                    localeString = this.Locale.Evaluate(process);
                }
                string timezone = null;

                if (this.Timezone != null)
                {
                    timezone = this.Timezone.Evaluate(process);
                }

                CultureInfo locale;

                if (localeString == null)
                {
                    locale = process.Bot.Config.Locale;
                }
                else
                {
                    try {
                        locale = CultureInfo.CreateSpecificCulture(localeString.Replace('_', '-'));
                    } catch (CultureNotFoundException) {
                        process.Log(LogLevel.Warning, "In element <date>: Locale '" + localeString + "' is unknown.");
                        locale = process.Bot.Config.Locale;
                    }
                }

                var      date = DateTime.Now;
                TimeSpan offset;

                if (timezone != null && TimeSpan.TryParse(timezone, out offset))
                {
                    offset = -offset;
                }
                else
                {
                    offset = TimeZoneInfo.Local.GetUtcOffset(DateTime.UtcNow);
                }

                if (format != null)
                {
                    if (jformat != null)
                    {
                        process.Log(LogLevel.Warning, "In element <date>: format and jformat are both specified. format will be used.");
                    }
                    return(DateUnixFormat(new DateTimeOffset(date, offset), format, locale));
                }

                if (jformat != null)
                {
                    return(DateJavaFormat(new DateTimeOffset(date, offset), jformat, locale));
                }

                return(date.Date.ToString(locale));
            }
示例#17
0
        internal Response ProcessRequest(Request request, bool trace, bool useTests, int recursionDepth, out TimeSpan duration)
        {
            var stopwatch = Stopwatch.StartNew();
            var that      = this.Normalize(request.User.GetThat());

            // Respond to each sentence separately.
            var builder = new StringBuilder();

            foreach (var sentence in request.Sentences)
            {
                var process = new RequestProcess(sentence, recursionDepth, useTests);

                process.Log(LogLevel.Diagnostic, "Normalized text: " + sentence.Text);

                string output;
                try {
                    var template = request.User.Graphmaster.Search(sentence, process, that, trace);
                    if (template != null)
                    {
                        process.template = template;
                        process.Log(LogLevel.Diagnostic, "Input matched user-specific category '" + process.Path + "'.");
                    }
                    else
                    {
                        template = this.Graphmaster.Search(sentence, process, that, trace);
                        if (template != null)
                        {
                            process.template = template;
                            process.Log(LogLevel.Diagnostic, "Input matched category '" + process.Path + "' in file '" + Path.GetFileName(template.FileName) + "'.");
                        }
                    }

                    if (template != null)
                    {
                        output = template.Content.Evaluate(process);
                    }
                    else
                    {
                        process.Log(LogLevel.Warning, "No match for input '" + sentence.Text + "'.");
                        output = this.Config.DefaultResponse;
                    }
                } catch (TimeoutException) {
                    output = this.Config.TimeoutMessage;
                } catch (RecursionLimitException) {
                    output = this.Config.RecursionLimitMessage;
                } catch (LoopLimitException) {
                    output = this.Config.LoopLimitMessage;
                }

                output = output.Trim();

                if (output.Length > 0)
                {
                    if (builder.Length != 0)
                    {
                        builder.Append(' ');
                    }
                    builder.Append(output);
                }

                process.Finish();
            }

            var response = new Response(request, builder.ToString());

            request.Response = response;

            stopwatch.Stop();
            duration = stopwatch.Elapsed;
            return(response);
        }
示例#18
0
            public override string Evaluate(RequestProcess process)
            {
                string jformat = null; string format = null;

                if (this.JFormat != null)
                {
                    jformat = this.JFormat.Evaluate(process);
                }
                DateTime start; DateTime end;
                string   startString, endString;

                // Parse the dates.
                startString = this.Start.Evaluate(process);
                try {
                    if (jformat == null)
                    {
                        start = DateTime.Parse(startString);
                    }
                    else
                    {
                        format = ConvertJavaFormat(jformat);
                        start  = DateTime.ParseExact(startString, jformat, CultureInfo.CurrentCulture, DateTimeStyles.AllowWhiteSpaces | DateTimeStyles.AssumeLocal | DateTimeStyles.AdjustToUniversal);
                    }
                } catch (FormatException) {
                    if (format == null)
                    {
                        process.Log(LogLevel.Warning, "In element <interval>: Could not parse '" + startString + "' as a date.");
                    }
                    else
                    {
                        process.Log(LogLevel.Warning, "In element <interval>: Could not parse '" + startString + "' as a date with format '" + jformat + "'.");
                    }
                    return("unknown");
                }

                endString = this.End.Evaluate(process);
                try {
                    if (jformat == null)
                    {
                        end = DateTime.Parse(endString);
                    }
                    else
                    {
                        format = ConvertJavaFormat(jformat);
                        end    = DateTime.ParseExact(endString, jformat, CultureInfo.CurrentCulture, DateTimeStyles.AllowWhiteSpaces | DateTimeStyles.AssumeLocal | DateTimeStyles.AdjustToUniversal);
                    }
                } catch (FormatException) {
                    if (format == null)
                    {
                        process.Log(LogLevel.Warning, "In element <interval>: Could not parse '" + endString + "' as a date.");
                    }
                    else
                    {
                        process.Log(LogLevel.Warning, "In element <interval>: Could not parse '" + endString + "' as a date with format '" + jformat + "'.");
                    }
                    return("unknown");
                }

                // Output the result.
                string unit = this.Style.Evaluate(process);

                switch (unit)
                {
                case "milliseconds": return(((int)(end - start).TotalMilliseconds).ToString());

                case "seconds": return(((int)(end - start).TotalSeconds).ToString());

                case "minutes": return(((int)(end - start).TotalMinutes).ToString());

                case "hours": return(((int)(end - start).TotalHours).ToString());

                case "days": return(((int)(end - start).TotalDays).ToString());

                case "weeks": return((((int)(end - start).TotalDays) / 7).ToString());

                case "months":
                    int interval = (end.Year - start.Year) * 12 + end.Month - start.Month;
                    if (end - new DateTime(end.Year, end.Month, 1, 0, 0, 0, end.Kind) <
                        start - new DateTime(start.Year, start.Month, 1, 0, 0, 0, start.Kind))
                    {
                        // end falls earlier in the month than start.
                        --interval;
                    }
                    return(interval.ToString());

                case "years":
                    interval = end.Year - start.Year;
                    if (end - new DateTime(end.Year, 1, 1, 0, 0, 0, end.Kind) <
                        start - new DateTime(start.Year, 1, 1, 0, 0, 0, start.Kind))
                    {
                        // end falls earlier in the year than start.
                        --interval;
                    }
                    return(interval.ToString());

                default:
                    process.Log(LogLevel.Warning, "In element <interval>: The style parameter evaluated to an invalid unit: " + unit);
                    return("unknown");
                }
            }