2009-07-25 19 views
0

我也有類似的爲*的.sln格式的配置格式,所以採取以下爲例:如何解析文本中的多級「節點」?

DCOM Productions Configuration File, Format Version 1.0 

BeginSection:Global 
    GlobalKeyA = AnswerOne 

    .: Stores the global configuration key 
    :: for the application. This key is used 
    :: to save the current state of the app. 
    :: as well as prevent lockups 
    GlobalKey3 = AnswerTwo 

    .: Secondary Key. See above setting 
    GlobalKeyC = AnswerThree 

    BeginSection: UpdateSystem 
     NestedKeyA = One 
     NestedKeyB = Two 
     NestedKeyC = { A set of multiline data 
         where we will show how 
         to write a multiline 
         paragraph } 
     NestedKeyD = System.Int32, 100 
    EndSection 
EndSection 

BeginSection:Application 
    InstallPath = C:\Program Files\DCOM Productions\BitFlex 
EndSection 

我知道我需要一個遞歸函數可能是採用文字的段作爲參數的話,例如,將整個部分傳遞給它,並遞歸地解析它。

我似乎無法讓我的腦袋圍繞如何做到這一點。每個部分可能會有更多的子部分。這就像一個Xml文檔..我沒有真正要求代碼,只是一個關於如何解析文檔的方法。

我正在考慮使用選項卡(指定索引)來確定我正在使用哪一節,但如果文檔沒有正確選項卡(格式化),則會失敗。有更好的想法嗎?

回答

2

也許你可以在這種格式和XML之間繪製並行。 即 BeginSection < ==> 「<開口>」 EndSection < ==> 「< /閉合>」

把它看成是與許多根元素的XML文件。 BeginSection和EndSection內部的內容將是您的內部xml節點,例如 NestedKeyA =作爲節點名稱,「One」作爲值。

。:似乎是一條評論,所以你可以跳過它。 System.Int32,100 - 可以是屬性和節點

值{A組多數據 的,我們將展示如何 寫多 段落} - 你可以拿出算法解析這也是。

+0

呀,開始和EndSection的基本上都是年底開始停止節點,但我會如何區分EndSection之間屬於哪個BeginSection?我不能只抓住第一個,因爲它可能是嵌套節點的EndSection,而不是第一個被解析的節點。 – 2009-07-25 01:15:33

0

好吧,我做到了。 * *

/// <summary> 
/// Reads and parses xdf strings 
/// </summary> 
public sealed class XdfReader { 
    /// <summary> 
    /// Instantiates a new instance of the DCOMProductions.BitFlex.IO.XdfReader class. 
    /// </summary> 
    public XdfReader() { 
     // 
     // TODO: Any constructor code here 
     // 
    } 

    #region Constants 

    /// <devdoc> 
    /// This regular expression matches against a section beginning. A section may look like the following: 
    /// 
    ///  SectionName:Begin 
    ///  
    /// Where 'SectionName' is the name of the section, and ':Begin' represents that this is the 
    /// opening tag for the section. This allows the parser to differentiate between open and 
    /// close tags. 
    /// </devdoc> 
    private const String SectionBeginRegularExpression = @"[0-9a-zA-Z]*:Begin"; 

    /// <devdoc> 
    /// This regular expression matches against a section ending. A section may look like the following: 
    /// 
    ///  SectionName:End 
    ///  
    /// Where 'SectionName' is the name of the section, and ':End' represents that this is the 
    /// closing tag for the section. This allows the parser to differentiate between open and 
    /// close tags. 
    /// </devdoc> 
    private const String SectionEndRegularExpression = @"[0-9a-zA-Z]*:End"; 

    /// <devdoc> 
    /// This regular expression matches against a key and it's value. A key may look like the following: 
    /// 
    ///  KeyName=KeyValue 
    ///  KeyName = KeyValue 
    ///  KeyName =KeyValue 
    ///  KeyName= KeyValue 
    ///  KeyName =  KeyValue 
    ///     
    /// And so on so forth. This regular expression matches against all of these, where the whitespace 
    /// former and latter of the assignment operator are optional. 
    /// </devdoc> 
    private const String KeyRegularExpression = @"[0-9a-zA-Z]*\s*?=\s*?[^\r]*"; 

    #endregion 

    #region Methods 

    public void Flush() { 
     throw new System.NotImplementedException(); 
    } 

    private String GetSectionName(String xdf) { 
     Match sectionMatch = Regex.Match(xdf, SectionBeginRegularExpression); 

     if (sectionMatch.Success) { 
      String retVal = sectionMatch.Value; 
      retVal = retVal.Substring(0, retVal.IndexOf(':')); 
      return retVal; 
     } 
     else { 
      throw new BitFlex.IO.XdfException("The specified xdf did not contain a valid section."); 
     } 
    } 

    public XdfFile ReadFile(String fileName) { 
     throw new System.NotImplementedException(); 
    } 

    public XdfKey ReadKey(String xdf) { 
     Match keyMatch = Regex.Match(xdf, KeyRegularExpression); 

     if (keyMatch.Success) { 
      String name = keyMatch.Value.Substring(0, keyMatch.Value.IndexOf('=')); 
      name = name.TrimEnd(' '); 

      XdfKey retVal = new XdfKey(name); 

      String value = keyMatch.Value.Remove(0, keyMatch.Value.IndexOf('=') + 1); 
      value = value.TrimStart(' '); 

      retVal.Value = value; 
      return retVal; 
     } 
     else { 
      throw new BitFlex.IO.XdfException("The specified xdf did not contain a valid key."); 
     } 
    } 

    public XdfSection ReadSection(String xdf) { 
     if (ValidateSection(xdf)) { 
      String[] rows = xdf.Split(new String[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); 
      XdfSection rootSection = new XdfSection(GetSectionName(rows[0])); System.Diagnostics.Debug.WriteLine(rootSection.Name); 

      do { 
       Match beginMatch = Regex.Match(xdf, SectionBeginRegularExpression); 
       beginMatch = beginMatch.NextMatch(); 

       if (beginMatch.Success) { 
        Match endMatch = Regex.Match(xdf, String.Format("{0}:End", GetSectionName(beginMatch.Value))); 

        if (endMatch.Success) { 
         String sectionXdf = xdf.Substring(beginMatch.Index, (endMatch.Index + endMatch.Length) - beginMatch.Index); 
         xdf = xdf.Remove(beginMatch.Index, (endMatch.Index + endMatch.Length) - beginMatch.Index); 

         XdfSection section = ReadSection(sectionXdf); System.Diagnostics.Debug.WriteLine(section.Name); 

         rootSection.Sections.Add(section); 
        } 
        else { 
         throw new BitFlex.IO.XdfException(String.Format("There is a missing section ending at index {0}.", endMatch.Index)); 
        } 
       } 
       else { 
        break; 
       } 
      } while (true); 

      MatchCollection keyMatches = Regex.Matches(xdf, KeyRegularExpression); 

      foreach (Match item in keyMatches) { 
       XdfKey key = ReadKey(item.Value); 
       rootSection.Keys.Add(key); 
      } 

      return rootSection; 
     } 
     else { 
      throw new BitFlex.IO.XdfException("The specified xdf did not contain a valid section."); 
     } 
    } 

    private Boolean ValidateSection(String xdf) { 
     String[] rows = xdf.Split(new String[] { "\r\n" }, StringSplitOptions.None); 

     if (Regex.Match(rows[0], SectionBeginRegularExpression).Success) { 
      if (Regex.Match(rows[rows.Length - 1], SectionEndRegularExpression).Success) { 
       return true; 
      } 
      else { 
       return false; 
      } 
     } 
     else { 
      return false; 
     } 
    } 

    #endregion 
} 

}