2010-09-27 2 views
2

(Это очень похоже на мой последний вопрос, но я просто понял, что пытался решить неправильную проблему)Как разбить эту строку на запятую, но только если она соответствует этим критериям?

Я создаю что-то вроде jQuery, и я пытаюсь разобрать селектор. Таким образом, учитывая что-то вроде этого:

a[href="http://weird.url/has,commas"], strong 

Как я могу разделить это на

a[href="http://weird.url/has,commas"] 
strong 

?

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


Модифицированная версия решения Макса:

static IEnumerable<string> SplitSelectors(string str) 
    { 
     int openBrackets = 0; 
     int lastIndex = 0; 

     for (int i = 0; i < str.Length; ++i) 
     { 
      switch (str[i]) 
      { 
       case '[': 
        openBrackets++; 
        break; 
       case ']': 
        openBrackets--; 
        break; 
       case ',': 
        if (openBrackets == 0) 
        { 
         yield return str.Substring(lastIndex, i - lastIndex); 
         lastIndex = i + 1; 
        } 
        break; 
      } 
     } 
     yield return str.Substring(lastIndex); 
    } 

я игнорирую кавычки, потому что я не думаю, что они должны происходить вне селектора атрибутов в любом случае. Я пытаюсь подражать спецификациям jQuery, но я не совсем уверен, что они в этом сценарии.

+0

Поскольку вы говорите о разборе, возможно, вам будет проще смотреть на другие пути, которые делают эту работу за вас? http://htmlagilitypack.codeplex.com/ и http://jint.codeplex.com/ – t0mm13b

+0

@ tommieb75: Я уже использую 'HtmlAgilityPack' в этом проекте. Это не Html, который я пытаюсь разобрать на данный момент, просто Html-селекторов. – mpen

+0

ahhh! справедливо! – t0mm13b

ответ

2
static List<string> SplitByComma(string str) 
    { 
     bool quoted = false; 
     bool attr = false; 
     int start = 0; 
     var result = new List<string>(); 
     for(int i = 0; i < str.Length; ++i) 
     { 
      switch(str[i]) 
      { 
       case '[': 
        if(!quoted) attr = true; 
        break; 
       case ']': 
        if(!quoted) attr = false; 
        break; 
       case '\"': 
        if(!attr) quoted = !quoted; 
        break; 
       case ',': 
        if(!quoted && !attr) 
        { 
         result.Add(str.Substring(start, i - start)); 
         start = i + 1; 
        } 
        break; 
      } 
     } 
     if(start < str.Length) 
      result.Add(str.Substring(start)); 
     return result; 
    } 
+0

Я не думаю, что значение атрибута обязательно должно быть процитировано, и в этом случае у вас могут быть некотируемые запятые, которые до сих пор не должны быть взорваны. – mpen

+0

исправлено (как я думаю) для этого случая, если нет, вы должны предоставить более подробную информацию о грамматике выражения – max

+0

Достаточно хорошо. Я могу поправить это по мере необходимости, это похоже на хороший подход. – mpen

1

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

for each char in text 
    if char is quote 
    if escaped = true 
     escaped = false 
    else 
     escaped = true 
    else if char is comma 
    if escaped = true 
     add char to token 
    else 
     begin new token 
    else 
    add char to token 

где escaped указывает ли вы в кавычках или нет.

+0

Не получится. Могут быть одиночные и двойные кавычки. Например, «blah» blah'' будет видеть двойную кавычку как открытую цитату, но это не так, потому что ее избегают другие кавычки. Или это может быть экранировано с помощью '\' (да ... я didn Я не говорю об этом. Может быть, мне стоит просто посмотреть, является ли это атрибутом и забыть все остальное. – mpen