2011-01-10 1 views
1

J'ai un String qui contient les éléments suivants:bonne façon d'analyser la chaîne de requête

workarea = Londres + & + Accueil + Counties + Ltd & sous = fs & & & fash * 5

qui ressemble à une chaîne de requête URI. Quelle est la meilleure façon d'analyser les éléments de cette chaîne (workarea et sub) sans se tromper avec la manipulation de chaînes?

Si j'utilise HttpUtility.ParseQueryString est bloqué car les deux éléments incluent &. Cependant, si je code tout d'abord, je perds les séparations des éléments. Idéalement, la sortie serait:

  • workarea = Londres & Home Counties Ltd
  • sub = fs & & & fash * 5
+1

Il suffit d'utiliser 'Server.URLEncode' pour coder chaque valeur .. –

+0

Thats ce que je suis cherche à faire - mais je dois d'abord séparer ces valeurs –

+0

'ParseQueryString' est la meilleure option. '? name = black & white' est valide, mais ne veut pas dire ce que vous voulez dire. De plus, '+ 'pour les espaces sont grossièrement obsolètes. Où avez-vous trouvé cette chaîne? – Kobi

Répondre

0

Je pense que vous avez besoin de faire un peu d'encodage ... Vous semblez vouloir utiliser & comme délimiteur et comme donnée sans avoir besoin d'être échappé. Un analyseur simple ne sera pas en mesure de dire quelle utilisation vous voulez dire (comme lorsque vous avez essayé la méthode ParseQueryString).

Si vous savez ce que vos noms d'éléments possibles (par exemple workarea, sous), vous pouvez alors l'utiliser pour déterminer plus précisément ce qui & sont délimiteurs et qui sont données par assuing que tout & suivi d'un nom d'élément est un séparateur et les autres ne le sont pas. Je pense que cela va entrer dans le domaine de "jouer avec la manipulation de cordes" si ...

Mon premier plan d'action serait cependant de changer ce que ma chaîne d'entrée était si possible de le rendre plus bien défini et moins ambigu .

+0

Je suis d'accord avec cela, rendre la chaîne d'entrée moins ambigu – Xander

-1

Je me trouvais à écrire un blog post récemment à ce sujet qui contient également un classe d'utilitaire de petite taille pour manipuler les paramètres de chaîne de requête. Voici quelques exemples de cas d'utilisation (tirés de mon article):

QueryStringHelper qsh = new QueryStringHelper("?page=5&username=dan&year=2010&enabled=true&[email protected]"); 

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 

J'espère que vous le trouverez utile.

+2

Est-ce que cela concerne réellement le problème original de & as data par opposition aux délimiteurs? Je n'ai pas regardé votre classe QSH mais j'imagine que si elle est destinée aux querystrings, elle supposera que tous sont des délimiteurs. – Chris

+0

@Chris - Vous avez raison. Je n'ai évidemment pas lu la question correctement. –

2

Vous pouvez utiliser cette fonction personnalisée ... show test rapide que la chaîne que vous avez donné à l'origine dans la question, il retourne la sortie désirée qui est deux éléments, l'un avec la clé sub et la valeur fs&&&FASh*5 et une autre avec clé workarea et la valeur 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; 
} 

Comme je l'ai dit dans le commentaire, si elle est utilisée pour une utilisation réelle querystring Server.URLEncode pour coder chaque valeur.

explication rapide: au lieu d'analyser la chaîne de requête selon & qui ne peut être fait, il cherche = caractères, une fois trouvé commencer à chercher & qui apparaissent avant.

+0

Belle solution. J'espère juste qu'il n'y a pas de possibilité pour et dans les touches aussi. :) – Chris

+0

@Chris lol qui sera beaucoup trop .. et rendre tout cela avec un grand drapeau rouge Impossible. ;-) –

0

Cela peut être une bonne utilisation d'une expression régulière.Bien sûr, cela dépend de votre définition exacte, mais voici ce que je pris:

  • Une clé ne peut pas contenir & ou = - sinon vous avez ambiguïté.
  • Les valeurs ne peuvent pas contenir = - nous pouvons être capable de contourner celui-là, mais c'est beaucoup plus simple de cette façon.
  • Une valeur sera trouvée jusqu'à la fin de la chaîne, ou jusqu'à ce qu'il y ait une autre perluète. Si vous avez plusieurs esperluette à la fin de la valeur, cela devrait bien fonctionner: a=12&&&&b=3 - > a=12&&&, b=3

Voici le code:

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

Maintenant, vous avez une collection de clés et de valeurs, où sur chaque Match la deuxième Group est la clé (index 1), et la troisième est la valeur (index 2).
Par exemple, vous pouvez convertir les matchs à un dictionnaire (si vous n'avez pas clés dupliquées):

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