2013-09-18 32 views
0

Я пытаюсь создать парсер регулярных выражений для одного блока XML.Regex XML parsing C#

Я знаю, что люди скажут, что Regex не является хорошим планом для xml, но я работаю с данными потока, и мне просто нужно знать, был ли передан полный блок xml и находится в буфере.

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

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

Вот мое регулярное выражение, отформатированное для визуальной помощи.

Я балансирую группу, а также группу и проверяя, что они не существуют в конце сегментов выражения.

/* 
    ^(?<TAG>[<] 
     (?![?]) 
     (?<TAGNAME>[^\s/>]*) 
    ) 
    (?<ParamData> 
     (
      (\" 
       (?> 
        \\\"| 
        [^"]| 
        \"(?<quote>)| 
        \"(?<-quote>) 
       )* 
       (?(quote)(?!)) 
       \" 
      )| 
      [^/>] 
     )*? 
    ) 
    (?: 
     (?<HASCONTENT>[>])| 
     (?<-TAG> 
      (?<TAGEND>/[>]) 
     ) 
    ) 
    (?(HASCONTENT) 
     (
      (?<CONTENT> 
       (
        (?<inTAG>[<]\<TAGNAME>)(?<-inTAG>/[>])?| 
        (?<-inTAG>[<]/\<TAGNAME>[>])| 
        ([^<]+|[<](?![/]?\<TAGNAME>)) 
       )*? 
       (?(inTAG)(?!)) 
      ) 
     ) 
     (?<TAGEND>(?<-TAG>)[<]/\<TAGNAME>[>]) 
    ) 
    (?(TAG)(?!)) 
*/ 

В моем классе я ожидаю, что любой возвращаемый объект Null означает, что в очереди не было блока xml.

Вот класс, который я использую.

(я использовал символьной строки (@ «»), чтобы ограничить требования к эвакуации, все "символы были заменены на„“форматировать правильно.

public class XmlDataParser 
{ 
    // xmlObjectExpression defined below to limit code highlight errors 
    private Regex _xmlRegex; 
    private Regex xmlRegex 
    { 
     get 
     { 
      if (_xmlRegex == null) 
      { 
       _xmlRegex = new Regex(xmlObjectExpression); 
      } 
      return _xmlRegex; 
     } 
    } 

    private string backingStore = ""; 

    public bool HasObject() 
    { 
     return (backingStore != null) && xmlRegex.IsMatch(backingStore); 
    } 
    public string GetObject() 
    { 
     string result = null; 
     if (HasObject()) 
     { 
      lock (this) 
      { 
       Match obj = xmlRegex.Match(backingStore); 
       result = obj.Value; 
       backingStore = backingStore.Substring(result.Length); 
      } 
     } 
     return result; 
    } 

    public void AddData(byte[] bytes) 
    { 
     lock (this) 
     { 
      backingStore += System.Text.Encoding.Default.GetString(bytes); 
     } 
    } 

    private static string xmlObjectExpression = @"^(?<TAG>[<](?![?])(?<TAGNAME>[^\s/>]*))(?<ParamData>((\""(?>\\\""|[^""]|\""(?<quote>)|\""(?<-quote>))*(?(quote)(?!))\"")|[^/>])*?)(?:(?<HASCONTENT>[>])|(?<-TAG>(?<TAGEND>/[>])))(?(HASCONTENT)((?<CONTENT>((?<inTAG>[<]\<TAGNAME>)(?<-inTAG>/[>])?|(?<-inTAG>[<]/\<TAGNAME>[>])|([^<]+|[<](?![/]?\<TAGNAME>)))*?(?(inTAG)(?!))))(?<TAGEND>(?<-TAG>)[<]/\<TAGNAME>[>]))(?(TAG)(?!))"; 



} 
+0

, если все, что вы хотите знать, если это полный XML-блок, передать его в XmlDocument и делать нагрузку на него. это будет намного быстрее, чем ваш регулярное выражение подход – Alex

+4

'Я знаю, что люди скажут что Regex не является хорошим планом для xml' Regex - неплохой план для xml. – Jonesopolis

+0

> «Анализ синтаксиса Regex XML» OOPS ... Ошибка в моем парсере. Rebooting ... –

ответ

4

Просто используйте XmlReader и кормить его в TextReader. Для прочитать потоки, вы хотите изменить ConformanceLevel фрагменту.

XmlReaderSettings settings = new XmlReaderSettings(); 
    settings.ConformanceLevel = ConformanceLevel.Fragment; 
    using (XmlReader reader = XmlReader.Create(tr,settings)) 
    { 
       while (reader.Read()) 
       { 
        switch (reader.NodeType) 
        { 
// this is from my code. You'll rewrite this part : 

         case XmlNodeType.Element: 
          if (t != null) 
          { 
           t.SetName(reader.Name); 
          } 
          else if (reader.Name == "event") 
          { 
           t = new Event1(); 
           t.Name = reader.Name; 
          } 
          else if (reader.Name == "data") 
          { 
           t = new Data1(); 
           t.Name = reader.Name; 
          } 
          else 
          { 
           throw new Exception(""); 
          } 

          break; 
         case XmlNodeType.Text: 
          if (t != null) 
          { 
           t.SetValue(reader.Value); 
          } 
          break; 
         case XmlNodeType.XmlDeclaration: 
         case XmlNodeType.ProcessingInstruction: 
          break; 
         case XmlNodeType.Comment: 
          break; 
         case XmlNodeType.EndElement: 
          if (t != null) 
          { 
           if (t.Name == reader.Name) 
           { 

            t.Close(); 
            t.Write(output); 
            t = null; 
           } 
          } 

          break; 
         case XmlNodeType.Whitespace: 
          break; 
        } 
       } 
    } 
+0

как бы я хотел получить только завершенные блоки из потока в этот момент. И будет ли это работать на TcpStream? –

+0

@VolureDarkAngel - см. Мое редактирование –

+0

Я очень ценю конструктивную информацию о XmlReader, знаете ли вы, что XmlReader будет работать на потоке tcp? Я начну играть с ним в ближайшее время, чтобы определить, выполнит ли она нужную мне задачу. –