簡體   English   中英

您如何解析文本中的多級“節點”?

[英]How do you parse multi-level “nodes” in text?

我的配置格式類似於* .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文檔。我在這里並不是真正的要求代碼,只是一種有關如何解析這樣的文檔的方法。

我正在考慮使用選項卡(指定索引)來確定我正在使用的部分,但是如果文檔的選項卡未正確設置(格式),這將失敗。 有更好的想法嗎?

也許您可以在這種格式和XML之間進行平行繪制。 即BeginSection <==>“ <開頭>” EndSection <==>“ </結束>”

可以將其視為具有許多根元素的XML文件。 BeginSection和EndSection內部將是您的內部xml節點,例如NestedKeyA =作為節點名稱,“ One”作為值。

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

{一組多行數據,我們將在其中顯示如何編寫多行段落}-您也可以使用算法來解析此內容。

好吧,我做到了。 * *

/// <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
}

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM