[英]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.