Хороший способ разобрать строку запроса - PullRequest
1 голос
/ 10 января 2011

У меня есть String, который содержит следующее:

? Workarea = Лондон + & + Home + графства + Ltd и суб = фс &&& FASH * 5

, которая напоминает строку запроса URI. Как лучше всего проанализировать элементы этой строки (workarea и sub), не беспокоясь о манипуляции со строками?

Если я использую HttpUtility.ParseQueryString, он застревает, так как оба элемента включают &. Однако, если я сначала все закодирую, я потеряю разделение элементов. В идеале вывод будет:

  • workarea = London & Home Countyties Ltd
  • sub = fs &&& FASh * 5

Ответы [ 4 ]

2 голосов
/ 10 января 2011

Вы можете использовать эту пользовательскую функцию ... быстрый тест покажет, что со строкой, которую вы изначально задали в вопросе, он возвращает желаемый результат, который состоит из двух элементов: один с ключом 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 для кодирования каждого значения.

Краткое объяснение: вместо синтаксического анализа строки запроса в соответствии с &, что не может быть выполнено, он ищет = символов, при обнаружении начинает искать &, которые появляются раньше.

0 голосов
/ 10 января 2011

Это может быть хорошим использованием регулярного выражения.Конечно, это зависит от вашего точного определения, но вот что я взял:

  • Ключ не может содержать & или = - в противном случае у вас есть неоднозначность.
  • Значения не могутсодержать = - мы можем быть в состоянии обойти это, но это намного проще.
  • Значение будет соответствовать до конца строки или до ее появления.больше амперсанда.Если в конце значения есть несколько амперсандов, это должно работать хорошо: a=12&&&&b=3 -> 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"];
0 голосов
/ 10 января 2011

Я думаю, что вам нужно выполнить некоторую кодировку ... Вы, кажется, хотите использовать & как разделитель, так и как данные без необходимости экранирования. Простой парсер не сможет определить, какое использование вы имеете в виду (например, когда вы пытались использовать метод ParseQueryString).

Если вы знаете, каковы ваши возможные имена элементов (например, workarea, sub), вы можете использовать это, чтобы более точно определить, какие & являются разделителями, а какие - данными, предполагая, что любой &, за которым следует имя элемента, является разделителем, а любой другие нет. Я думаю, что это входит в сферу "возни с манипуляциями со строками", хотя ...

Тем не менее, мой первый путь действий будет состоять в том, чтобы изменить мою входную строку, если это возможно, чтобы сделать ее более четкой и менее двусмысленной.

0 голосов
/ 10 января 2011

Недавно я написал в блоге об этом, который также содержит небольшой служебный класс для манипулирования параметрами строки запроса.Вот несколько примеров использования (взято из моего поста):

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

Надеюсь, вы найдете его полезным.

...