protected XmlObservableParser(bool caseSensitive) { comparer = caseSensitive ? StringComparer.Ordinal : StringComparer.OrdinalIgnoreCase; id = Character(char.IsLetter) .And( Character(char.IsLetterOrDigit).NoneOrMore()) .Join(); const char tagStartChar = '<'; const char tagEndChar = '>'; tagStart = Character(tagStartChar); tagEnd = Character(tagEndChar); tagName = id; openTag = (namePredicate, attributes) => from _ in tagStart from name in tagName.Where(namePredicate) from attrs in attributes from __ in InsignificantWhiteSpace from empty in Character('/').Maybe() from ___ in tagEnd select Tuple.Create(name, attrs, empty.Any()); attributeDelimiter = Character('\'').Or(Character('"')); attributeName = id; attributeValue = from delimeter in attributeDelimiter from value in AnyCharacterUntil(delimeter) from _ in Character(delimeter) select value; attribute = predicate => from _ in InsignificantWhiteSpace from name in attributeName.Where(predicate) from __ in InsignificantWhiteSpace from ___ in Character('=') from ____ in InsignificantWhiteSpace from value in attributeValue select new XAttribute(name, value); closeTag = from _ in tagStart.And(Character('/')) from name in tagName from __ in InsignificantWhiteSpace from ___ in tagEnd select name; text = AnyCharacterUntil(tagStartChar).Select(t => new XText(t)); comment = from _ in Word(tagStartChar + "!--") from value in AnyCharacterUntil("--") from __ in Word("--" + tagEndChar) select new XComment(value); string startCData = tagStartChar + "![CDATA["; string endCData = "]]" + tagEndChar; cData = from _ in Word(startCData) from value in AnyCharacterUntil(endCData) from __ in Word(endCData) select new XCData(value); element = (namePredicate, attributes, elementContent) => from _ in InsignificantWhiteSpace let open = openTag(namePredicate, attributes) from tag in open from isEmpty in tag.Item3 from children in isEmpty ? open.Success(Observable.Empty <XObject>()) : elementContent.IgnoreTrailing( InsignificantWhiteSpace.IgnoreBefore( closeTag)) from array in tag.Item2.Concat(children).ToArray() select new XElement(tag.Item1, array); }