如何在 C# 中拆分 OData 多级扩展查询字符串?
How to Split OData multi-level expand query string in C#?
我有一个URL:Expand=User($select=Firstname,Lastname),Organisation,Contract($Expand=MyOrganisation($select=Name,Status),Organisation),List
我需要按以下格式拆分此字符串:
User($select=Firstname,Lastname)
Organisation
Contract($Expand=MyOrganisation($select=Name,Status),Organisation)
List
如何在C#中实现这个功能?
您更有可能必须使用 ODataLib with in-built URI Parser
Uri requestUri = new Uri("Products?$select=ID&$expand=ProductDetail" +
"&$filter=Categories/any(d:d/ID%20gt%201)&$orderby=ID%20desc" +
"&$top=1&$count=true&$search=tom",
UriKind.Relative);
ODataUriParser parser = new ODataUriParser(model, serviceRoot, requestUri);
SelectExpandClause expand = parser.ParseSelectAndExpand(); // parse $select, $expand
FilterClause filter = parser.ParseFilter(); // parse $filter
OrderByClause orderby = parser.ParseOrderBy(); // parse $orderby
SearchClause search = parser.ParseSearch(); // parse $search
long? top = parser.ParseTop(); // parse $top
long? skip = parser.ParseSkip(); // parse $skip
bool? count = parser.ParseCount(); // parse $count
添加 RegExp 选项(Amal 在下面提供的固定版本)
string url = "User($select=Firstname,Lastname),Organisation,Contract($Expand=MyOrganisation($select=Name,Status),Organisation),List";
Regex rgx = new Regex(@"(.+?)(?:(\(.*?\)),|,)");
foreach (var match in rgx.Matches($"{url},"))
{
Console.WriteLine(match.ToString()[..^1]);
}
您不仅需要拆分字符串,还需要在拆分时跟踪括号。这对于普通的旧正则表达式是不可能的。参见 this post。
但是,可以使用一些高级 RegEx 来实现拆分; .NET 幸运地支持 balancing groups using which you can keep track of the parentheses. This answer 对提出解决方案很有帮助。为了可读性,我将正则表达式拆分为多行并使用 RegexOptions.IgnorePatternWhitespace
:
string url = "User($select=Firstname,Lastname),Organisation,Contract($Expand=MyOrganisation($select=Name,Status),Organisation),List";
Regex rgx = new Regex(
@"(.+?)
(
(
\(
(?:
[^()]
|
(?'open'\()
|
(?'close-open'\))
)+
(?(open)(?!))
\)
)
,
|
,
|
\b$
)",
RegexOptions.IgnorePatternWhitespace);
foreach(var match in rgx.Matches(url))
{
Console.WriteLine($"{match.Groups[1]} {match.Groups[3]}");
}
字段将作为 match.Groups[1]
提供,参数(如果有的话)将作为 match.Groups[3]
提供(如果没有参数,这将是一个空字符串)。您可以访问 match.Groups[0]
以获取整个组。
正则表达式分解
Regex
Description
(.+?)
Non-greedily match one or more characters
\(
and \)
Match an actual (
and )
[^()]
Match any character that is not a (
or )
(?'open'\()
Create a named group with the name "open" and match a (
character
(?'close-open\))
Create a group "close" and assign the interval between "open" and "close" to "close" and delete group "open"
(?(open)(?!))
Assert if the "open" group is not deleted
(?:[^()]|(?'open'\()|(?'close-open'\)))+
Create a non-capturing group and match one or more characters that match one of the expressions between |
我有一个URL:Expand=User($select=Firstname,Lastname),Organisation,Contract($Expand=MyOrganisation($select=Name,Status),Organisation),List
我需要按以下格式拆分此字符串:
User($select=Firstname,Lastname)
Organisation
Contract($Expand=MyOrganisation($select=Name,Status),Organisation)
List
如何在C#中实现这个功能?
您更有可能必须使用 ODataLib with in-built URI Parser
Uri requestUri = new Uri("Products?$select=ID&$expand=ProductDetail" +
"&$filter=Categories/any(d:d/ID%20gt%201)&$orderby=ID%20desc" +
"&$top=1&$count=true&$search=tom",
UriKind.Relative);
ODataUriParser parser = new ODataUriParser(model, serviceRoot, requestUri);
SelectExpandClause expand = parser.ParseSelectAndExpand(); // parse $select, $expand
FilterClause filter = parser.ParseFilter(); // parse $filter
OrderByClause orderby = parser.ParseOrderBy(); // parse $orderby
SearchClause search = parser.ParseSearch(); // parse $search
long? top = parser.ParseTop(); // parse $top
long? skip = parser.ParseSkip(); // parse $skip
bool? count = parser.ParseCount(); // parse $count
添加 RegExp 选项(Amal 在下面提供的固定版本)
string url = "User($select=Firstname,Lastname),Organisation,Contract($Expand=MyOrganisation($select=Name,Status),Organisation),List";
Regex rgx = new Regex(@"(.+?)(?:(\(.*?\)),|,)");
foreach (var match in rgx.Matches($"{url},"))
{
Console.WriteLine(match.ToString()[..^1]);
}
您不仅需要拆分字符串,还需要在拆分时跟踪括号。这对于普通的旧正则表达式是不可能的。参见 this post。
但是,可以使用一些高级 RegEx 来实现拆分; .NET 幸运地支持 balancing groups using which you can keep track of the parentheses. This answer 对提出解决方案很有帮助。为了可读性,我将正则表达式拆分为多行并使用 RegexOptions.IgnorePatternWhitespace
:
string url = "User($select=Firstname,Lastname),Organisation,Contract($Expand=MyOrganisation($select=Name,Status),Organisation),List";
Regex rgx = new Regex(
@"(.+?)
(
(
\(
(?:
[^()]
|
(?'open'\()
|
(?'close-open'\))
)+
(?(open)(?!))
\)
)
,
|
,
|
\b$
)",
RegexOptions.IgnorePatternWhitespace);
foreach(var match in rgx.Matches(url))
{
Console.WriteLine($"{match.Groups[1]} {match.Groups[3]}");
}
字段将作为 match.Groups[1]
提供,参数(如果有的话)将作为 match.Groups[3]
提供(如果没有参数,这将是一个空字符串)。您可以访问 match.Groups[0]
以获取整个组。
正则表达式分解
Regex | Description |
---|---|
(.+?) |
Non-greedily match one or more characters |
\( and \) |
Match an actual ( and ) |
[^()] |
Match any character that is not a ( or ) |
(?'open'\() |
Create a named group with the name "open" and match a ( character |
(?'close-open\)) |
Create a group "close" and assign the interval between "open" and "close" to "close" and delete group "open" |
(?(open)(?!)) |
Assert if the "open" group is not deleted |
(?:[^()]|(?'open'\()|(?'close-open'\)))+ |
Create a non-capturing group and match one or more characters that match one of the expressions between | |