public IEnumerable <Expression> ParseHtmlQuery(ParameterExpression elementParm, ParameterExpression keyValueParm, ParameterExpression valueParm, string htmlQueryString) { var expressions = new List <Expression>(); Expression expression = null; var builder = new StringBuilder(); using (var stream = new MemoryStream(Encoding.Default.GetBytes(htmlQueryString ?? string.Empty))) { using (var reader = new StreamReader(stream)) { while (reader.Peek() != -1) { if (reader.Peek() == '[') { reader.Read(); var str = GetNestedElement(reader, new[] { ']' }); var delimitors = new[] { "*=", "~=", "^=", "|=", "$=", "!=", "=" }; var values = new List <string>(); if (delimitors.Any(str.Contains)) { var delimitor = delimitors.First(str.Contains); values.AddRange(str.Split(new[] { delimitor }, StringSplitOptions.RemoveEmptyEntries)); values = values.Select(v => v.Trim()).ToList(); values[1] = values[1].Substring(1, values[1].Length - 2); // removes parenthesis surrounding value values.Add(delimitor); } if (!values.Any()) { expression = keyValueParm.CreateStringPropertyCompareExpression(str, "Key", PredicateBuilder.StringTransform.ToLowerInvariant, PredicateBuilder.StringComparison.Equals); } else { var keyExpression = keyValueParm.CreateStringPropertyCompareExpression(values.First(), "Key", PredicateBuilder.StringTransform.ToLowerInvariant, PredicateBuilder.StringComparison.Equals); Expression valueExpression; var enumerableMethodName = PredicateBuilder.EnumerableMethodName.Any; if (values.Last() == "|=") { var valueExpression1 = keyValueParm.CreateStringPropertyCompareExpression(values[1], valueParm, PredicateBuilder.StringTransform.None, PredicateBuilder.StringComparison.Equals); var valueExpression2 = keyValueParm.CreateStringPropertyCompareExpression(values[1] + "-", valueParm, PredicateBuilder.StringTransform.None, PredicateBuilder.StringComparison.StartsWith); valueExpression = Expression.OrElse(valueExpression1, valueExpression2); } else { var stringComparison = PredicateBuilder.StringComparison.Equals; switch (values.Last()) { case "!=": stringComparison = PredicateBuilder.StringComparison.NotEquals; break; case "$=": stringComparison = PredicateBuilder.StringComparison.EndsWith; break; case "^=": stringComparison = PredicateBuilder.StringComparison.StartsWith; break; case "*=": stringComparison = PredicateBuilder.StringComparison.Contains; break; case "~=": stringComparison = PredicateBuilder.StringComparison.Equals; break; } if (stringComparison == PredicateBuilder.StringComparison.NotEquals) { valueExpression = Expression.Not(keyValueParm.CreateStringPropertyCompareExpression(values[1], valueParm, PredicateBuilder.StringTransform.None, PredicateBuilder.StringComparison.Equals)); } else { valueExpression = keyValueParm.CreateStringPropertyCompareExpression(values[1], valueParm, PredicateBuilder.StringTransform.None, stringComparison); } } if (values.Last() == "!=") { var valuesExpression = keyValueParm.CreateKeyValueBoolExpression <string>(valueParm, valueExpression, enumerableMethodName); var expression2 = Expression.OrElse(Expression.Not(keyExpression), valuesExpression); expression = Expression.OrElse(Expression.Not(elementParm.CreateAnyExpression()), expression2); } else { var valuesExpression = keyValueParm.CreateKeyValueBoolExpression <string>(valueParm, valueExpression, enumerableMethodName); expression = Expression.AndAlso(keyExpression, valuesExpression); } } } else if (reader.Peek() == ':') { var str = GetNestedElement(reader, new[] { ' ', ',', '.', '>', '+', '~', '#' }); } else if (reader.Peek() == ',') { reader.Read(); expression = builder.ToString().Trim().Length > 0 ? CreateStringPropertyCompareExpressionHelper(builder, elementParm, keyValueParm, valueParm) : expression; builder = new StringBuilder(); var expression1 = ParseHtmlQuery(elementParm, keyValueParm, valueParm, reader.ReadToEnd()); expression = Expression.OrElse(expression, expression1.First()); } else if (reader.Peek() == ' ') { var delimitors = new[] { '*', '~', '^', '|', '$', '!', '=', ' ', ',', '.', '>', '+', '~', '#' }; reader.Read(); if (!delimitors.Any(d => d == reader.Peek())) { if (builder.ToString().Trim().Length > 0) { expression = CreateStringPropertyCompareExpressionHelper(builder, elementParm, keyValueParm, valueParm); builder = new StringBuilder(); } expressions.Add(expression); expression = ParseHtmlQuery(elementParm, keyValueParm, valueParm, reader.ReadToEnd()).First(); } } else { builder.Append((char)reader.Read()); } } if (builder.ToString().Trim().Length > 0) { expression = CreateStringPropertyCompareExpressionHelper(builder, elementParm, keyValueParm, valueParm); } } } expressions.Add(expression); return(expressions); }