How to use css selector with "not" in c#? - c#

I want to find elements by css selector, but I want to skip some of them, how can I do it?
driver.FindElements(By.CssSelector("a[href]"))
but I need not to take href that has logoff and client/contract in it

You probably don't need LINQ for this. You can use the :not() pseudo-class, one for each value you want to exclude (note the *= in each negation; I'm assuming substring matches here):
driver.FindElements(By.CssSelector("a[href]:not([href*='logoff']):not([href*='client'])"))
An exception is if you have a dynamic list of values that you want to exclude: you can either build your selector programmatically using string.Join() or a loop and then pass it to By.CssSelector(), or you can follow Richard Schneider's answer using LINQ to keep things clean.

After using CSS to get the elements then use LINQ to filter on the href.
Using System.Linq;
string[] blackList = new string[] { "logoff, "client",... };
string[] urls = driver
.FindElements(By.CssSelector("a[href]"))
.Select(e => e.GetAttribute("href"))
.Where(url => !blackList.Any(b => url.Contains(b)))
.ToArray();
Checking the URL is case-sensitive, because that is what W3C states. You may want to change this.

Related

Linq query to exclude matching strings from c# list

I have a C# list full of strings.
I would like to exclude those items that match a specific pattern like those strings that start with "DST*"
Any string that doesn't start with DST, am happy to take, but anything that starts with DST I would like to remove from this list.
I see linq has Contains(). But how do I do the inverse of Contains()?
You can use the ! operator to inverse any bool:
var filtered = listOfStrings.Where(x => !x.StartsWith("DST"));
anything that starts with DST I would like to remove from this list.
You don't need LINQ you could also use List<T>.RemoveAll:
listOfStrings.RemoveAll(s => s.StartsWith("DST"));
But of course this modifies the original list and does not create a new. If that's desired use the approach from Somebody.

C# LINQ Contains method with two clauses

What is the best practice way to use two clauses in LINQ Contains method..
Title is string
This is my If statement :
if (oWeb.ParentWeb.Title.Contains("Ricky") || oWeb.ParentWeb.Title.Contains("John"))
I need solution like this :
if (oWeb.ParentWeb.Title.Contains("Ricky", "John"))
Since Title is string this actually has nothing to do with LINQ as the used Contains method is an instance method of string.
Assuming you have more strings to check, you can do something like that:
var strings = new[] {"Ricky", "John"};
if (strings.Any(oWeb.ParentWeb.Title.Contains))
// do something
But roryap's answer using a regex seems preferable (as long as the number of strings to check is not too big).
I don't think LINQ is the best option for that. Why not use regular expressions?
Regex.IsMatch(oWeb.ParentWeb.Title, "ricky|john", RegexOptions.IgnoreCase);
Contains takes only one parameter, so you cannot do it this way.
You can make an array of items, and check containment with it:
var titles = new[] {"Ricky", "John"};
if (titles.Any(t => oWeb.ParentWeb.Title.Contains(t))) {
...
}

How to Replace the generic css style into empty string using C#

When i take a list of items from one list, some css styles are added into that. I want to remove / Replace that.
The following code is used to replace the style generic. But it is not given the result.
flag.Text = flag.Text.Replace("style=[\"'](.*)[\"']", "");
But it is not replacing. How to give this. Or shall i use Contains method?
You probably want to try using Regex.Replace (and using Multiline option, just in case) instead of string.Replace:
RegexOptions options = RegexOptions.Multiline;
flag.Text = Regex.Replace(flag.Text, "style=[\"'](.*)[\"']", "", options);
What you show above is Replace using string.Replace. It tries to find exact match of the static text instead of text with pattern. If you want to replace text with pattern, use Regex.Replace instead.
I think you are trying to replace the style by using the string.replace() methode but i think it cant do a regex like replace. I think you need to take a look at Regex.Replace.

How do I get the case insensitive match in List<string>?

I have a list of words in a List. Using .Contains(), I can determine if a word is in the list. If a word I specify is in the list, how do I get the case sensitive spelling of the word from the list? For example, .Contains() is true when the word is "sodium phosphate" but the list contains "Sodium Phosphate". How do I perform a case-insensitive search ("sodium phosphate") yet return the case-sensitive match ("Sodium Phosphate") from the list?
I prefer to avoid a dictionary where the key is uppercase and the value is proper cased, or vice verse.
You want something like:
string match = list.FirstOrDefault(element => element.Equals(target,
StringComparison.CurrentCultureIgnoreCase));
This will leave match as a null reference if no match can be found.
(You could use List<T>.Find, but using FirstOrDefault makes the code more general, as it will work - with a using System.Linq; directive at the top of the file) on any sequence of strings.)
Note that I'm assuming there are no null elements in the list. If you want to handle that, you may want to use a static method call instead: string.Equals(element, target, StringComparison.CurrentCultureIgnoreCase).
Also note that I'm assuming you want a culture-sensitive comparison. See StringComparison for other options.
Consider if Dictionary with case insensitive comparison work for you. Unless you care about order of words Dictionary will give you much better performance of look up than list.
Dictionary<string, string> openWith =
new Dictionary<string, string>(
StringComparer.CurrentCultureIgnoreCase);
You can also use StringComparer in list
if (listOfValues.Contains(value, StringComparer.OrdinalIgnoreCase))

C# Regex: Get group names?

myRegex.GetGroupNames()
Seems to return the numbered groups as well... how do I get only the named ones?
A solution using the actual Match object would be fine as well.
Does using the RegexOptions.ExplicitCapture option when creating the regex do what you want ? e.g.
Regex theRegex = new Regex(#"\b(?<word>\w+)\b", RegexOptions.ExplicitCapture);
From MSDN:
Specifies that the only valid captures
are explicitly named or numbered
groups of the form (?<name>...). This
allows unnamed parentheses to act as
noncapturing groups without the
syntactic clumsiness of the expression
(?:...).
So you won't need to worry about whether users of your API may or may not use non-capturing groups if this option is set.
See the other comments/answers about using (?:) and/or sticking with "one style". Here is my best approach that tries to directly solve the question:
var named = regex.GetGroupNames().Where(x => !Regex.IsMatch(x, "^\\d+$"));
However, this will fail for regular expressions like (?<42>...).
Happy coding.
public string[] GetGroupNames(Regex re)
{
var groupNames = re.GetGroupNames();
var groupNumbers = re.GetGroupNumbers();
Contract.Assert(groupNames.Length == groupNumbers.Length);
return Enumerable.Range(0, groupNames.Length)
.Where(i => groupNames[i] != groupNumbers[i].ToString())
.Select(i => groupNames[i])
.ToArray();
}
Actually, this will still fail when the group name and number happen to be the same :\ But it will succeed even when the group name is a number, as long as the number is not the same as its index.

Categories

Resources