读取文本文件中的行,然后查看XML文件是否包含文本文件中出现的那些单词

时间:2012-08-19 22:15:41

标签: c# winforms

请耐心等待我,因为我对编程本身和C#winforms都很陌生。

我有一个AAA.txt文件,我在组合框中显示为“AAA”。我的主要目的是允许用户从下拉组合中选择AAA,然后单击搜索。在click事件中,函数应该逐行读取文本文件的内容,然后查找这些单词(例如hello)或短语(例如早上好)是否出现在我的所有20个XML文件的<description></description>子节点中。如果这些单词/短语确实出现在某些<description></description>子节点中,那么整个<item></item>父节点的数据将显示为结果。

AAA.txt:

hello
good morning
great
bye

我的功能:

private void searchComByKeywords()
{ 
    string[] fileEntries = Directory.GetFiles(sourceDir);
    foreach (string fileName in fileEntries)
    {
        XmlDocument xmlDoc = new XmlDocument();
        string docPath = fileName;
        xmlDoc.Load(docPath);
        XmlNodeList nodeList = xmlDoc.GetElementsByTagName("item");

        foreach (XmlNode node in nodeList)
        {
            XmlElement itemElement = (XmlElement)node;
            string itemDescription = itemElement.GetElementsByTagName("description")[0].InnerText;

            if (itemDescription.ToLower().Contains(comboTemplates.SelectedItem.ToString()))
            {
                string itemTitle = itemElement.GetElementsByTagName("title")[0].InnerText;
                string itemDate = itemElement.GetElementsByTagName("pubDate")[0].InnerText;
                string itemAuthor = itemElement.GetElementsByTagName("author")[0].InnerText;

                richComByTemplate.AppendText("Author: " + itemAuthor + "\nDate: " + itemDate + "\nTitle: " + itemTitle + "\nDescription: " + itemDescription + "\n\n--------\n\n");
            }
        }
    }
}

我知道有些人可能会告诉我使用LINQ-to-XML,但这不是我关注的问题。我知道这行if (itemDescription.ToLower().Contains(comboTemplates.SelectedItem.ToString()))没有做我想要的(它会搜索单词“AAA”而不是查看所选的AAA文本文件)。我是否可以知道如何正确地写这行以便阅读所选文本文件中出现的单词/短语?

谢谢。

1 个答案:

答案 0 :(得分:2)

静态System.IO.File类有一个方法ReadAllLines,它将文本文件的所有行读入数组。

string[] words = File.ReadAllLines(filepath);

如果组合仅包含文件名,您可能希望先用目录名称补充

string dir = @"C:\MyDataPath";
string filename = comboTemplates.SelectedItem.ToString();
string filepath = Path.Combine(dir, filename);

然后将单词放入HashSet<string>

var wordSet = new HashSet<string>(words);

然后使用正则表达式将您的描述分成单个单词

var descrWords = 
    new HashSet<string>(
        Regex.Matches(itemDescription.ToLower(), @"\w+")
        .Cast<Match>()
        .Select(m => m.Value)
    );
descrWords.UnionWith(wordSet);
if (descrWords.Count > 0) {
    // Your description contains at least one of the words
}

您可以通过多种不同方式进行比较。例如。使用LINQ

if (words.Union(
    Regex.Matches(itemDescription.ToLower(), @"\w+")
        .Cast<Match>()
        .Select(m => m.Value)
    ).Any())
{
    ...
}

注意:仅查看字符串是否包含带

的单词是不够的
s.Contains("great")

因为它会找到像“伟大”这样的词语部分。


如果您还需要查找短语,则上述方法不起作用。您需要将正则表达式搜索与循环或LINQ语句结合使用。让我们使用类型

的正则表达式
\bWordOrPhrase\b

\b匹配字边界。为了确保不在正则表达式中引入一些特殊的正则表达式字符,我们需要转义我们的单词或短语。

bool found = Regex.IsMatch(description, @"\b" + Regex.Escape(wordOrPhrase) + @"\b");

最后,我们必须对列表中的所有单词和短语进行此测试。让我们把所有东西放在一起:

string dir = @"C:\MyDataPath";
string filename = comboTemplates.SelectedItem.ToString();
string filepath = Path.Combine(dir, filename);

string[] words = File.ReadAllLines(filepath);

然后测试你的描述

string itemDescription = itemElement.GetElementsByTagName("description")[0].InnerText;
if (words.Any(
    wordOrPhrase =>
    Regex.IsMatch(itemDescription,
                  @"\b" + Regex.Escape(wordOrPhrase) + @"\b",
                  RegexOptions.IgnoreCase)))
{
    ...
}