我有2个xml文件: 一个是我需要过滤的大日志文件(原始数据), 另一个用作配置文件,用于指定我的查询以从大型日志文件中过滤数据。 这是我的两个xml文件的样子:
需要过滤的大型日志文件(下面仅显示一小部分)
<?xml version="1.0" encoding="UTF-8"?>
<Logging S="T006" version="2" >
<Log Date="2018-11-21" Severity="Info" id="22" ID="Opened" Msg="some text"/>
<Log Date="2018-11-21" Severity="Info" id="76" ID="Auth"/>
<Log Date="2018-11-21" Severity="Info" id="60" ID="Up"/>
<Log Date="2018-11-21" Severity="Info" id="22" ID="Opened" Msg="some text"/>
<Log Date="2018-11-21" Severity="Info" id="96" ID="Locked"/>
<Log Date="2018-11-21" Severity="Info" id="84" ID="Done"/>
<Log Date="2018-11-21" Severity="Info" id="57" ID="Idle"/>
<Log Date="2018-11-21" Severity="Info" id="10" ID="Inspected" Pos="12"/>
<Log Date="2018-11-21" Severity="Info" id="148" ID="Started"/>
<Log Date="2018-11-21" Severity="Error" id="38" ID="TechError" Msg="too low"/>
<Log Date="2018-11-21" Severity="Error" id="38" ID="TechError" Msg="too large"/>
<Log Date="2018-11-21" Severity="Error" id="38" ID="TechError" Msg="disabled"/>
<Log Date="2018-11-21" Severity="Error" id="38" ID="TechError" Msg="disabled"/>
<Log Date="2018-11-21" Severity="Error" id="87" ID="Validation"/>
<Log Date="2018-11-21" Severity="data" id="31" ID="Update" Path="~/Status/" From="T121003" To="T121637"/>
<Log Date="2018-11-21" Severity="data" id="31" ID="Update" Path="~/Status/" From="1" To="0"/>
<Log Date="2018-11-21" Severity="Warning" id="24" ID="Problem" Pos="12"/>
<Log Date="2018-11-21" Severity="Warning" id="26" ID="UI" Msg="popup"/>
<Log Date="2018-11-21" Severity="Warning" id="23" ID="Update" Path="Startup" From="1" To="0"/>
<Log Date="2018-11-21" Severity="Info" id="58" ID="System"/>
<Log Date="2018-11-21" Severity="Error" id="20" ID="Log" Msg="failed"/>
<Log Date="2018-11-21" Severity="System" id="50" ID="System"/>
<Log Date="2018-11-21" Severity="System" id="51" ID="Memory" />
</Logging>
下面是我要用来从中生成查询语句的xml(作为配置文件)
<?xml version="1.0" encoding="utf-8"?>
<Statuscodes xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Statuscode value="S01" text="Status code S01 ">
<Triggers id="1">
<Trigger searchField="Severity" searchText="Error" />
<Trigger searchField="ID" searchText="TechError" />
</Triggers>
<Causes>
<Cause shortText="this is the cause" longText="This is a very long description....." />
</Causes>
<Solutions>
<Solution value="SOL01" description="Description of solution" solutionSteps="Follow these steps..." page="2" />
<Solution value="SOL02" description="Description of solution 2" solutionSteps="or something else" page="3" />
</Solutions>
</Statuscode>
<Statuscode value="S02" text="Status code S02">
<Triggers id="2">
<Trigger searchField="Severity" searchText="Error" />
<Trigger searchField="ID" searchText="TechError" />
<Trigger searchField="Msg" searchText="disabled" />
</Triggers>
<Causes>
<Cause shortText="2-this is the cause" longText="This is a very long description....." />
</Causes>
<Solutions>
<Solution value="2-SOL01" description="Description of solution" solutionSteps="Follow URL" page="2" />
<Solution value="2-SOL02" description="Description of solution 2" solutionSteps="Do something else" page="3" />
</Solutions>
</Statuscode>
</Statuscodes>
到目前为止我的C#代码:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private List<StatusCode> statusCodes = new List<StatusCode>();
private void button1_Click(object sender, EventArgs e)
{
var dataSet = new DataSet();
dataSet.ReadXml(@"C:\Users\LargeLogFile.xml");
var errorLogDataset = new DataSet();
errorLogDataset.ReadXml(@"C:\Users\configFile.xml");
foreach (DataRow result in errorLogDataset.Tables["Statuscode"].Rows)
{
var statusCode = new StatusCode
{
Code = result["value"].ToString(),
Text = result["text"].ToString()
};
var MyQuery = String.Empty;
foreach (DataRow resultTrigger in errorLogDataset.Tables["Trigger"].Select("Triggers_Id = " + result[0].ToString()))
{
var trigger = new Trigger
{
SearchField = resultTrigger["searchField"].ToString(),
SearchText = resultTrigger["searchText"].ToString()
};
statusCode.Triggers.Add(trigger);
// Questions: is this the right way/syntax to make MyQuery statement?
MyQuery += trigger.SearchField + " = '" + trigger.SearchText + "' AND ";
}
MyQuery = MyQuery.TrimEnd(" AND ".ToCharArray());
//Question: can I pass MyQuery to Select like this?
DataRow[] temp = dataSet.Tables["Log"].Select(MyQuery);
statusCodes.Add(statusCode);
var bindingSource = new BindingSource
{
DataSource = dataSet,
DataMember = "Log"
};
dataGridView1.DataSource = bindingSource;
}
}
}
class Trigger
{
public string SearchField { get; set; }
public string SearchText { get; set; }
}
class StatusCode
{
public string Code { get; set; }
public string Text { get; set; }
public List<Trigger> Triggers { get; private set; }
public StatusCode()
{
Triggers = new List<Trigger>();
}
}
我的目的是从数据集中检索MyQuery结果数据,并在gridview中显示行和列。因此,通过这种方式,我可以过滤大型日志文件,并且只能看到我选择的内容。 通过断点,我可以看到:
我知道有很多关于datagridview和LINQ以及过滤的资料和实例,但是我找不到一些更具体和与我的情况类似的答案。请告诉我,我在代码中做错了什么? 预先感谢。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;
using System.Globalization;
namespace StatusTable
{
public partial class Form1 : Form
{
const string LOG_XML = @"C:\Users\LargeLogFile.xml";
const string STATUS_XML = @"C:\Users\configFile.xml";
enum Logic
{
AND,
OR
}
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
DataTable logging = new DataTable();
logging.Columns.Add("Date", typeof(DateTime));
logging.Columns.Add("Severity", typeof(string));
logging.Columns.Add("id", typeof(string));
logging.Columns.Add("ID", typeof(string));
logging.Columns.Add("Msg", typeof(string));
XDocument docLog = XDocument.Load(LOG_XML);
foreach (XElement log in docLog.Descendants("Log"))
{
DateTime date = (DateTime)log.Attribute("Date");
string severity = (string)log.Attribute("Severity");
string id = (string)log.Attribute("id");
string ID = (string)log.Attribute("ID");
string msg = (string)log.Attribute("Msg");
logging.Rows.Add(new object[] { date, severity, id, ID, msg });
}
XDocument docStatus = XDocument.Load(STATUS_XML);
Logic logic = Logic.AND;
foreach (XElement Statuscode in docStatus.Descendants("Statuscode"))
{
DataTable status = null;
List<KeyValuePair<string, object>> searchFields = new List<KeyValuePair<string, object>>();
foreach (XElement trigger in Statuscode.Descendants("Trigger"))
{
string searchField = (string)trigger.Attribute("searchField");
string searchText = (string)trigger.Attribute("searchText");
switch (searchField)
{
case "Date":
// logging.AsEnumerable().Where(x => x.Field<DateTime>(searchField) == (DateTime)trigger.Attribute(searchText)).CopyToDataTable(status, LoadOption.Upsert);
searchFields.Add(new KeyValuePair<string, object>(searchField, (DateTime)trigger.Attribute("searchText")));
break;
default:
//logging.AsEnumerable().Where(x => x.Field<string>(searchField) == searchText).CopyToDataTable(status, LoadOption.Upsert);
searchFields.Add(new KeyValuePair<string, object>(searchField, (string)trigger.Attribute("searchText")));
break;
}
dataGridView1.DataSource = status;
}
switch (logic)
{
case Logic.AND:
status = logging.AsEnumerable()
.Where(x => searchFields.All(field => (field.Value.GetType() == typeof(DateTime)) ? x.Field<DateTime>(field.Key) == (DateTime)field.Value : x.Field<string>(field.Key) == (string)field.Value))
.CopyToDataTable();
break;
case Logic.OR:
status = logging.AsEnumerable()
.Where(x => searchFields.Any(field => (field.Value.GetType() == typeof(DateTime)) ? x.Field<DateTime>(field.Key) == (DateTime)field.Value : x.Field<string>(field.Key) == (string)field.Value))
.CopyToDataTable();
break;
}
}
}
}
}
答案 0 :(得分:0)
我创建了数据表,您可以将其用作搜索结果的数据源。我使用Xml Linq。每次搜索的结果均处于数据表状态。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Linq;
namespace WindowsFormsApplication37
{
enum Logic
{
AND,
OR
}
public partial class Form1 : Form
{
const string LOG_XML_FILENAME = @"c:\temp\test1.xml";
const string STATUS_XML_FILENAME = @"c:\temp\test2.xml";
public Form1()
{
InitializeComponent();
}
private List<StatusCode> statusCodes = new List<StatusCode>();
private void button1_Click(object sender, EventArgs e)
{
DataTable errorLogDatatable = new DataTable();
errorLogDatatable.Columns.Add("Date", typeof(DateTime));
errorLogDatatable.Columns.Add("Severity", typeof(string));
errorLogDatatable.Columns.Add("id", typeof(string));
errorLogDatatable.Columns.Add("ID", typeof(string));
errorLogDatatable.Columns.Add("Msg", typeof(string));
XDocument docLog = XDocument.Load(LOG_XML_FILENAME);
foreach (XElement log in docLog.Descendants("Log"))
{
DateTime date = (DateTime)log.Attribute("Date");
string severity = (string)log.Attribute("Severity");
string id = (string)log.Attribute("id");
string ID = (string)log.Attribute("ID");
string msg = (string)log.Attribute("Msg");
errorLogDatatable.Rows.Add(new object[] { date, severity, id, ID, msg });
}
XDocument docStatus = XDocument.Load(STATUS_XML_FILENAME);
Logic logic = Logic.AND;
foreach (XElement Statuscode in docStatus.Descendants("Statuscode"))
{
StatusCode statusCode = new StatusCode()
{
Code = (string)Statuscode.Attribute("value"),
Text = (string)Statuscode.Attribute("text")
};
statusCodes.Add(statusCode);
DataTable status = null;
foreach (XElement trigger in Statuscode.Descendants("Trigger"))
{
string searchField = (string)trigger.Attribute("searchField");
string searchText = (string)trigger.Attribute("searchText");
statusCode.Triggers.Add(new Trigger() { SearchField = searchField, SearchText = (string)trigger.Attribute("searchText") });
}
switch (logic)
{
case Logic.AND:
status = errorLogDatatable.AsEnumerable()
.Where(x => statusCode.Triggers.All(field => x.Field<string>(field.SearchField) == field.SearchText))
.CopyToDataTable();
break;
case Logic.OR:
status = errorLogDatatable.AsEnumerable()
.Where(x => statusCode.Triggers.Any(field => x.Field<string>(field.SearchField) == field.SearchText))
.CopyToDataTable();
break;
}
var bindingSource = new BindingSource
{
DataSource = status,
};
dataGridView1.DataSource = bindingSource;
}
}
}
class Trigger
{
public string SearchField { get; set; }
public string SearchText { get; set; }
}
class StatusCode
{
public string Code { get; set; }
public string Text { get; set; }
public List<Trigger> Triggers { get; private set; }
public StatusCode()
{
Triggers = new List<Trigger>();
}
}
}