解析查询字符串的好方法

时间:2011-01-10 11:51:16

标签: asp.net parsing url uri urlencode

我有String,其中包含以下内容:

  ?

工作区=伦敦+&安培; +首页+县+有限公司&安培;分= FS&安培;&安培;&安培; FASH * 5

类似于URI查询字符串。在不弄乱字符串操作的情况下解析此字符串(workareasub)元素的最佳方法是什么?

如果我使用HttpUtility.ParseQueryString被卡住,因为这两个元素都包括&amp ;.但是,如果我首先对整个事物进行编码,我会失去元素的分离。理想情况下,输出将是:

  • workarea =伦敦& Home Counties Ltd
  • sub = fs&&& FASh * 5

4 个答案:

答案 0 :(得分:2)

你可以使用这个自定义函数...快速测试显示你在问题中最初给出的字符串它会返回所需的输出,即两个项目,一个键为sub,值为fs&&&FASh*5另一个使用键workarea和值London+&Home+Counties+Ltd

public Dictionary<string, string> ParseQueryString(string qs)
{
    Dictionary<string, string> items = new Dictionary<string, string>();
    string valueBuffer = string.Empty;
    string keyBuffer = string.Empty;
    bool lookingForValue = true;
    for (int i = qs.Length - 1; i >= 0; i--)
    {
        char curChar = qs[i];
        if (curChar.Equals('='))
        {
            lookingForValue = false;
            keyBuffer = string.Empty;
        }
        else if (curChar.Equals('&') && !lookingForValue)
        {
            items.Add(keyBuffer, valueBuffer);
            valueBuffer = string.Empty;
            lookingForValue = true;
        }
        else if (curChar.Equals('?'))
        {
            if (keyBuffer.Length > 0)
                items.Add(keyBuffer, valueBuffer);
            break;
        }
        else
        {
            if (lookingForValue)
                valueBuffer = curChar + valueBuffer;
            else
                keyBuffer = curChar + keyBuffer;
        }
    }

    return items;
}

正如我在评论中所说,如果用于真正的查询字符串,请使用Server.URLEncode对每个值进行编码。

快速解释:不是根据&解析无法完成的查询字符串,而是查找=个字符,当找到时开始查找之前出现的&

答案 1 :(得分:0)

我认为你需要做一些编码......你似乎想要&amp;既可以用作分隔符,也可以用作数据而无需转义。一个简单的解析器将无法分辨您的意思(就像您尝试使用ParseQueryString方法时那样)。

如果您知道您的可能元素名称是什么(例如workarea,sub),那么您可以使用它来更准确地确定哪个&amp;是分隔符,是通过平衡任何&amp;数据的数据。后跟元素名称是分隔符,而其他任何分隔符都不是。我认为这已经进入了“搞乱字符串操作”的领域,但是......

我的第一个行动方案是改变我的输入字符串,如果可能的话,使它更明确,更不明确。

答案 2 :(得分:0)

这可以很好地利用正则表达式。当然,这取决于你的确切定义,但这就是我所做的:

  • 密钥不能包含&= - 否则您会有歧义。
  • 值不能包含= - 我们可以能够解决那个问题,但这种方式更简单。
  • 一个值将匹配到字符串的结尾,或直到还有一个&符号。如果您在值的末尾有多个&符,则应该可以正常运行:a=12&&&&b=3 - &gt; a=12&&&b=3

以下是代码:

MatchCollection parameters = Regex.Matches(query, "([^?&=]+)=([^=]+)(?=&|$)");

现在你有一个键和值的集合,每个Match上的第二个Group是键(索引1),第三个是值(索引2)。
例如,您可以将匹配项转换为字典(如果您没有任何重复的键):

var values = parameters.Cast<Match>()
                .ToDictionary(m => m.Groups[1].Value,
                              m => HttpUtility.UrlDecode(m.Groups[2].Value),
                              StringComparer.OrdinalIgnoreCase);
string workAread = values["workarea"];

答案 3 :(得分:-1)

我最近写了一篇关于这个的blog post,它还包含一个用于操作查询字符串参数的小实用程序类。以下是一些示例用例(取自我的帖子):

QueryStringHelper qsh = new QueryStringHelper("?page=5&username=dan&year=2010&enabled=true&email=dan@example.com");

string username = qsh.GetByName("username"); // username = "dan"

qsh.Add("category", "products"); // adds a new key called "category" with the value "products"

qsh.AddOrReplace("year", "1999"); // changes the year value from "2010" to "1999"

int year = qsh.GetByName<int>("year"); // year = 1999

qsh.AddOrReplace("page", 6); // changes the value of "page" to "6"

bool enabled = qsh.GetByName<bool>("enabled"); // enabled = true

qsh.RemoveByName("email"); // removes the "email" key

string qs = qsh.GetQueryString(); // qs = "page=6&username=dan&year=1999&enabled=true&category=products";

int count = qsh.Count(); // count = 5

我希望你能发现它的用途。