我有一个项目,它读取每个构建区域的预期构建结果的 xml,并与构建日志进行比较以查看构建是否通过。现在,linq 在单独的结果行中显示每个条件,但是(因为我循环遍历每个 linq 结果行以检查是否成功)我需要能够在同一时间,而不是不同时间。否则我可能会检查日志文件的错误行。请注意,有时有两个成功标准,但并非总是如此。这只是我需要立即检查的两个条件。 为了进行此更改,我将 SuccessCriteria 标签移出“条件”标签并移至“条件”下方。进行此更改后,linq 不会获取 xml 行。我的完整 xml 中应该有大约 69 行 results_b ,但它选取了一些我没有显示为旧格式的部分。我尝试在 LINQ 中将 cName = (string)p.Attribute("name") 更改为 cName = (string)b.Attribute("name"),但结果相同。 cValue 同时也发生了类似的变化。
我的问题是,如何更改 LINQ 以获取完整的 xml 文件,以及如何更改 groupBy_b 以同时检查这两个条件?我希望将条件放在一个列表中,但周围还有其他数据,例如构建机器、进程名称和成功标准。 例如,对于某些日志,ParseISLogStats,我放入 xml 中的表看起来像这样(因此我需要检查日志中的 BuildProject 和 BaseBuildArea 是否正确,因为它们是不同的列,但成功标准对于这两个来说只有一个条件):
ParseISLogStats Desctiption=nightly v17 partb Projects=8 Status=Success
ParseISLogStats Description=nightly v17 partb Projects=8 Status=Success
ParseISLogStats Description=nightly v17 Projects=33 Status=Success
到目前为止,我有这段代码(添加了 groupBy 来尝试将条件一起放入列表中):
void ReadXml()
{
int i_results = 0; //0 is successful for all; if it increases we have failed in one
XmlDocument xml = new XmlDocument();
string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string newPath = Path.GetFullPath(Path.Combine(path, @"..\.."));
string finalPathXmlb = Path.GetFullPath(Path.Combine(newPath, @"BuildVerificationBuildAttributes_b.xml")); //new format
teamPost = "";
//linq
XDocument xmlDoc2 = XDocument.Load(finalPathXmlb);
//XElement buildVerificationElement = xmlDoc1.Element("BuildVerification");
//IEnumerable<XElement> buildElements = buildVerificationElement.Elements("build");
//IEnumerable<XElement> buildMachines = buildElements.Elements("BuildMachine");
//get just the times from the xml
//var codeFreezeTime = xmlDoc1.Descendants("codeFreezeTime").First()?.Value;
//logToFileAndScreen(codeFreezeTime);
//get build info from xml, such as process (log name), condition, successCriteria, build machine, start time header,
IEnumerable<XElement> processes = buildMachines.Elements("Process");
var results_b =
xmlDoc2.Descendants("build")
.SelectMany(b => b.Descendants("Process")
.SelectMany(p => p.Descendants("Condition")
.SelectMany(c => c.Descendants("SuccessCriteria")
.Select(sc => new
{
buildMach = (string)b.Element("BuildMachine"),
p1 = (string)p.Element("ProcessName"),
startTimeHeader = (string)p.Element("startTimeHeader"),
cName = (string)c.Attribute("name"),
cValue = (string)c.Attribute("value"),
f1 = (string)sc.Element("field"),
c1 = (string)sc.Element("comparison"),
v1 = (string)sc.Element("value")
})))).ToList();
var groups_b = results_b.GroupBy(x => new { build_machine = x.buildMach, process_name = x.p1, name = x.cName }).ToList();
} //ParseLogFile
我希望我的 groups_b 看起来像这样(但由于 linq 不工作,它永远不会这样做,但我认为如果 linq 工作的话,我的 groups_b 中的它也不正确):
{buildMach = mach64, p1=ParseISLogStats, startTimeHeader = StartTime, {cName=Description, cValue=nightly v17 partb, cName=Projects, cValue=8}, f1=Status, c1=equal, v1=Succcess}
{buildmach = mach64, p1=ParseISLogStats, startTimeheader = StartTime, {cName=Description, cValue = nightly v17, cName=Projects, cValue=33},f1=status, c1=equal, v1=Success}
这就是我的 xml 的样子:
<?xml version="1.0" encoding="UTF-8"?>
<BuildVerification>
<codeFreezeTime>19:00</codeFreezeTime>
<build>
<BuildMachine>mach31</BuildMachine>
<Process>
<ProcessName>SpinFileVersionStats</ProcessName>
<startTimeHeader>StartTime</startTimeHeader>
<Conditions>
<Condition
name='VersionFile' value="\\view\Build_NightlyDeveloper\R\filename1.cs">
</Condition>
</Conditions>
<SuccessCriteria>
<field>Status</field>
<comparison>equal</comparison>
<value>Success</value>
</SuccessCriteria>
</Process>
<Process>
<ProcessName>SpinFileVersionStats</ProcessName>
<startTimeHeader>StartTime</startTimeHeader>
<Conditions>
<Condition
name='VersionFile' value="\\view\Build_NightlyDeveloper\R\filename2.cs">
</Condition>
</Conditions>
<SuccessCriteria>
<field>Status</field>
<comparison>equal</comparison>
<value>Success</value>
</SuccessCriteria>
</Process>
<Process>
<ProcessName>SpinFileVersionStats</ProcessName>
<startTimeHeader>StartTime</startTimeHeader>
<Conditions>
<Condition
name='VersionFile' value="\\view\Build_NightlyDeveloper\R\filename3.h">
</Condition>
</Conditions>
<SuccessCriteria>
<field>Status</field>
<comparison>equal</comparison>
<value>Success</value>
</SuccessCriteria>
</Process>
</build>
<build>
<BuildMachine>mach46</BuildMachine>
<Process>
<ProcessName>SpinFileVersionStats</ProcessName>
<startTimeHeader>StartTime</startTimeHeader>
<Conditions>
<Condition
name='VersionFile' value="\\view\Build_NightlyDeveloper\K\filename4.cs">
</Condition>
</Conditions>
<SuccessCriteria>
<field>Status</field>
<comparison>equal</comparison>
<value>Success</value>
</SuccessCriteria>
</Process>
<Process>
<ProcessName>SpinFileVersionStats</ProcessName>
<startTimeHeader>StartTime</startTimeHeader>
<Conditions>
<Condition
name='VersionFile' value="\\view\Build_NightlyDeveloper\K\fiename5.h">
</Condition>
</Conditions>
<SuccessCriteria>
<field>Status</field>
<comparison>equal</comparison>
<value>Success</value>
</SuccessCriteria>
</Process>
<Process>
<ProcessName>SpinFileVersionStats</ProcessName>
<startTimeHeader>StartTime</startTimeHeader>
<Conditions>
<Condition
name='VersionFile' value="\\view\Build_NightlyDeveloper\K\filename6.cs">
</Condition>
</Conditions>
<SuccessCriteria>
<field>Status</field>
<comparison>equal</comparison>
<value>Success</value>
</SuccessCriteria>
</Process>
<Process>
<ProcessName>SpinFileVersionStats</ProcessName>
<startTimeHeader>StartTime</startTimeHeader>
<Conditions>
<Condition
name='VersionFile' value="\\view\Build_NightlyDeveloper\D\filename7.cs">
</Condition>
</Conditions>
<SuccessCriteria>
<field>Status</field>
<comparison>equal</comparison>
<value>Success</value>
</SuccessCriteria>
</Process>
<Process>
<ProcessName>SpinFileVersionStats</ProcessName>
<startTimeHeader>StartTime</startTimeHeader>
<Conditions>
<Condition
name='VersionFile' value="\\view\Build_NightlyDeveloper\K\K\filename8.cs">
</Condition>
</Conditions>
<SuccessCriteria>
<field>Status</field>
<comparison>equal</comparison>
<value>Success</value>
</SuccessCriteria>
</Process>
<Process>
<ProcessName>SpinFileVersionStats</ProcessName>
<startTimeHeader>StartTime</startTimeHeader>
<Conditions>
<Condition
name='VersionFile' value="\\view\Build_NightlyDeveloper\K\K\filename9.h">
</Condition>
</Conditions>
<SuccessCriteria>
<field>Status</field>
<comparison>equal</comparison>
<value>Success</value>
</SuccessCriteria>
</Process>
<Process>
<ProcessName>SpinFileVersionStats</ProcessName>
<startTimeHeader>StartTime</startTimeHeader>
<Conditions>
<Condition
name='VersionFile' value="\\view\Build_NightlyDeveloper\K\K\filename11.cs">
</Condition>
</Conditions>
<SuccessCriteria>
<field>Status</field>
<comparison>equal</comparison> <!--can't use >= here -->
<value>Success</value>
</SuccessCriteria>
</Process>
<Process>
<ProcessName>SpinFileVersionStats</ProcessName>
<startTimeHeader>StartTime</startTimeHeader>
<Conditions>
<Condition
name='VersionFile' value="\\view\Build_NightlyDeveloper\K\filename22.cs">
</Condition>
</Conditions>
<SuccessCriteria>
<field>Status</field>
<comparison>equal</comparison>
<value>Success</value>
</SuccessCriteria>
</Process>
<Process>
<ProcessName>SpinFileVersionStats</ProcessName>
<startTimeHeader>StartTime</startTimeHeader>
<Conditions>
<Condition
name='VersionFile' value="\\view\Build_NightlyDeveloper\K\filename33.cs">
</Condition>
</Conditions>
<SuccessCriteria>
<field>Status</field>
<comparison>equal</comparison>
<value>Success</value>
</SuccessCriteria>
</Process>
<Process>
<ProcessName>SpinISProjectVersionStats</ProcessName>
<startTimeHeader>StartTime</startTimeHeader>
<Conditions>
<Condition
name='ProductName' value="P1">
</Condition>
</Conditions>
<SuccessCriteria>
<field>Status</field>
<comparison>equal</comparison>
<value>Success</value>
</SuccessCriteria>
</Process>
<Process>
<ProcessName>SpinISProjectVersionStats</ProcessName>
<startTimeHeader>StartTime</startTimeHeader>
<Conditions>
<Condition
name='ProductName' value="P2">
</Condition>
</Conditions>
<SuccessCriteria>
<field>Status</field>
<comparison>equal</comparison>
<value>Success</value>
</SuccessCriteria>
</Process>
<Process>
<ProcessName>SpinISProjectVersionStats</ProcessName>
<startTimeHeader>StartTime</startTimeHeader>
<Conditions>
<Condition
name='ProductName' value="P3">
</Condition>
</Conditions>
<SuccessCriteria>
<field>Status</field>
<comparison>equal</comparison>
<value>Success</value>
</SuccessCriteria>
</Process>
<Process>
<ProcessName>GetSWStats</ProcessName>
<startTimeHeader>StartTime</startTimeHeader>
<Conditions>
<Condition
name='DestinationPath' value="D:\Builds\Retail\nightly">
</Condition>
<Condition
name='DestinationPath' value="D:\Builds\Retail\nightly">
</Condition>
</Conditions>
<SuccessCriteria>
<field>Status</field>
<comparison>equal</comparison>
<value>Successful</value>
</SuccessCriteria>
</Process>
<Process>
<ProcessName>ParseISLogStats</ProcessName>
<startTimeHeader>StartTime</startTimeHeader>
<Conditions>
<Condition
name='Nightly' value="D:\nightly V17">
</Condition>
<Condition
name='Projects' value=33>
</Condition>
</Conditions>
<SuccessCriteria>
<field>Status</field>
<comparison>equal</comparison>
<value>Success</value>
</SuccessCriteria>
</Process>
<Process>
<ProcessName>ParseISLogStats</ProcessName>
<startTimeHeader>StartTime</startTimeHeader>
<Conditions>
<Condition
name='Nightly' value="D:\nightly V17 partb">
</Condition>
<Condition
name='Projects' value=8>
</Condition>
</Conditions>
<SuccessCriteria>
<field>Status</field>
<comparison>equal</comparison>
<value>Success</value>
</SuccessCriteria>
</Process>
<Process>
<ProcessName>ParseISLogStats</ProcessName>
<startTimeHeader>StartTime</startTimeHeader>
<Conditions>
<Condition
name='BuildProject' value="DInstallerBuild">
</Condition>
<Condition
name='BaseBuildArea' value="D:\R_Builds\K\v2.1\nightly">
</Condition>
</Conditions>
<SuccessCriteria>
<field>Status</field>
<comparison>equal</comparison>
<value>Success</value>
</SuccessCriteria>
</Process>
<Process>
<ProcessName>ParseISLogStats</ProcessName>
<startTimeHeader>StartTime</startTimeHeader>
<Conditions>
<Condition
name='BuildProject' value="KInstallerBuild">
</Condition>
<Condition
name='BaseBuildArea' value="D:\R_Builds\K\v2.1\nightly">
</Condition>
</Conditions>
<SuccessCriteria>
<field>Status</field>
<comparison>equal</comparison>
<value>Success</value>
</SuccessCriteria>
</Process>
</build>
</BuildVerification>
当您以这种方式链接
.SelectMany()
LINQ 函数时,最终的 .Select()
只能访问最新/最里面的 SuccessCriteria
元素。
您需要嵌套它们,而不是链接函数。比如:
var results_b = xmlDoc2.Descendants("build")
.SelectMany(b => b.Descendants("Process")
.SelectMany(p => p.Descendants("Condition")
.SelectMany(c => c.Descendants("SuccessCriteria")
.Select(sc => new {
buildMach = (string)b.Element("BuildMachine"),
p1 = (string)p.Element("ProcessName"),
startTimeHeader = (string)p.Element("startTimeHeader"),
cName = (string)c.Attribute("name"),
cValue = (string)c.Attribute("value"),
f1 = (string)sc.Element("field"),
c1 = (string)sc.Element("comparison"),
v1 = (string)sc.Element("value")
})
)
)
)
.ToList();
如果您不喜欢上面的深度嵌套,您可以考虑使用 LINQ 查询语法,它允许您构建嵌套元素的集合,并且仍然可以在最终的 select 子句中访问所有这些元素。
var results_b = (
from b in xmlDoc2.Descendants("build")
from p in b.Descendants("Process")
from c in p.Descendants("Condition")
from sc in c.Descendants("SuccessCriteria")
select new {
buildMach = (string)b.Element("BuildMachine"),
p1 = (string)p.Element("ProcessName"),
startTimeHeader = (string)p.Element("startTimeHeader"),
cName = (string)c.Attribute("name"),
cValue = (string)c.Attribute("value"),
f1 = (string)sc.Element("field"),
c1 = (string)sc.Element("comparison"),
v1 = (string)sc.Element("value")
})
.ToList();
(注意:我使用了一个外部工具(该工具将保持匿名)来协助这些翻译,但已经审查了结果的合理性。)