/// <summary> /// Creates a clone of the current node /// </summary> /// <returns>A new OpenNode instance</returns> public override Node Clone() { OpenNode node = new OpenNode(this.Name, "", this.Closed); for (int i = 0; i < this.Count; i++) { string attr = this.GetAttributeName(i); node.AddAttribute(attr, this.GetAttribute(attr)); } return(node); }
/// <summary> /// Parses an AOML string into open, close and content nodes /// </summary> /// <param name="aoml">The aoml string to be parsed</param> public NodeCollection Parse(string aoml) { NodeCollection nodes = new NodeCollection(); // Create regular expression instance if (this.regex == null) { this.regex = new Regex( "[<]\\s*(?<closer>[/]?)\\s*" + "(?<name>[a-z]+)" + "(\\s+((?<attribute>[a-z_\\-]+)\\s*" + "(=\\s*(" + /**/ (Mode == ParserMode.Strict ? "" : "(?<value>[^\\s<>'\"]+)|") + /**/ "[\"](?<value>[^\"]*)[\"]|" + /**/ (Mode == ParserMode.Compatibility ? "['](?<value>[^'>]*)[']?)|" : "['](?<value>[^']*)['])|") + /**/ "(?<value>)" + ")?)\\s*)*" + "\\s*(?<closed>[/]?)[>]", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Multiline); } // Some setup int regexCloser = this.regex.GroupNumberFromName("closer"); int regexName = this.regex.GroupNumberFromName("name"); int regexAttribute = this.regex.GroupNumberFromName("attribute"); int regexValue = this.regex.GroupNumberFromName("value"); int regexClosed = this.regex.GroupNumberFromName("closed"); // Convert to unix line endings aoml = aoml.Replace("\r\n", "\n"); // Parse AOML MatchCollection matches = this.regex.Matches(aoml); int offset = 0; foreach (Match match in matches) { // Extract content if (match.Index > offset) { string content = aoml.Substring(offset, match.Index - offset); AddContent(nodes, content, content); } offset = match.Index + match.Length; // Extract tag string raw = match.Groups[0].Value; string name = match.Groups[regexName].Value; if (string.IsNullOrEmpty(name)) { // No name, let's assume it's just text AddContent(nodes, raw, raw); continue; } bool closer = !string.IsNullOrEmpty(match.Groups[regexCloser].Value); bool closed = !string.IsNullOrEmpty(match.Groups[regexClosed].Value); if (closer) { // Closing tag nodes.Add(new CloseNode(name, raw)); } else { // Opening tag OpenNode node = new OpenNode(name, raw, closed); // Add attributes for (int i = 0; i < match.Groups[regexAttribute].Captures.Count; i++) { node.AddAttribute( match.Groups[regexAttribute].Captures[i].Value, match.Groups[regexValue].Captures[i].Value); } nodes.Add(node); } } // Remainder is content if (offset < aoml.Length) { string content = aoml.Substring(offset); AddContent(nodes, content, content); } return(nodes); }