Я пытаюсь создать файл Xml с помощью XDocument и LINQ на основе файла, который читается локально с моего компьютера. Это кажется довольно простым (и это так), пока я не хочу иметь дело с чем-то конкретным.Добавить узлы и группировать
Итак, я хочу, чтобы мой код, чтобы поддерживать как этот формат
<FailReport>
<SystemDescription>
<SystemID>system1</SystemID>
<ReportDate>DATE</ReportDate>
<SpecFile>file1</SpecFile>
<UUT>unit1</UUT>
</SystemDescription>
<FailDescription>
<Test1>tst1</Test1>
<Test2>tst2</Test2>
<TestType>typ1</TestType>
<Component>cmp1</Component>
<LowerLimit>llimit</LowerLimit>
<UpperLimit>ulimit</UpperLimit>
<MeasuredValue>value</MeasuredValue>
</FailDescription>
</FailReport>
и этот формат
<FailReport>
<SystemDescription>
<SystemID>system1</SystemID>
<ReportDate>DATE</ReportDate>
<SpecFile>file1</SpecFile>
<UUT>unit1</UUT>
</SystemDescription>
<FailDescription>
<Test1>tst1</Test1>
<Test2>tst2</Test2>
<TestType>typ1</TestType>
<Component>cmp1</Component>
<LowerLimit>llimit</LowerLimit>
<UpperLimit>ulimit</UpperLimit>
<MeasuredValue>value</MeasuredValue>
</FailDescription>
<FailDescription>
<Test1>tst3</Test1>
<Test2>tst4</Test2>
<TestType>typ2</TestType>
<Component>cmp2</Component>
<LowerLimit>llimit3</LowerLimit>
<UpperLimit>ulimit4</UpperLimit>
<MeasuredValue>value1</MeasuredValue>
</FailDescription>
</FailReport>
У меня есть функция, которая принимает параметры, как это:
public void newFail(string Tst1, string Tst2, string TestType, string Component, string LowerLimit, string UpperLimit, string MeasuredValue, string SystemID, string ReportDate, string SpecFile, string UUT)
В этой функции мне нужно сделать несколько вещей:
- Если Xml не существует в местоположении, мне нужно его создать и заполнить;
- Если он существует, загрузите файл и отредактируйте его;
- Если где-то в файле Xml уже существует запись типа «May7,2014 18:44», примените второй формат (сохраните «header», который является «SystemDescription», но добавьте второй/третий/wtv «FailDescription», блок с различными параметрами для «Test1», «Test2» и так далее
- Если он не существует использовать первый формат и создать «новый блок»
Это код, у меня есть атм..:
void newFail(string Tst1, string Tst2, string TestType, string Component, string LowerLimit, string UpperLimit, string MeasuredValue, string SystemID, string ReportDate, string SpecFile, string UUT)
{
if (doesElementExist("FailReport", "SystemDescription", "ReportDate", ReportDate)) //If an element with the same Report Date exists, add it to the same parent
{
ictLog.Element("FailReport").Elements("SystemDescription").Last(c => (string)c.Element("ReportDate").Value == ReportDate).Add(new XElement("FailDescription",
new XElement("Tst1", Tst1),
new XElement("Tst2", Tst2),
new XElement("TestType", TestType),
new XElement("Component", Component),
new XElement("LowerLimit", LowerLimit),
new XElement("UpperLimit", UpperLimit),
new XElement("MeasuredValue", MeasuredValue)));
}
else
{ //Otherwise add a new Parent
if (!firstEntry)
{
ictLog.Element("FailReport").Add(new XElement("FailReport",
new XElement("SystemDescription",
new XElement("SystemID", SystemID),
new XElement("ReportDate", ReportDate),
new XElement("SpecFile", SpecFile),
new XElement("UUT", UUT)),
new XElement("FailDescription",
new XElement("Tst1", Tst1),
new XElement("Tst2", Tst2),
new XElement("TestType", TestType),
new XElement("Component", Component),
new XElement("LowerLimit", LowerLimit),
new XElement("UpperLimit", UpperLimit),
new XElement("MeasuredValue", MeasuredValue))));
}
else
{
firstEntry = false;
ictLog = new XDocument(new XElement("FailReport",
new XElement("SystemDescription",
new XElement("SystemID", SystemID),
new XElement("ReportDate", ReportDate),
new XElement("SpecFile", SpecFile),
new XElement("UUT", UUT)),
new XElement("FailDescription",
new XElement("Tst1", Tst1),
new XElement("Tst2", Tst2),
new XElement("TestType", TestType),
new XElement("Component", Component),
new XElement("LowerLimit", LowerLimit),
new XElement("UpperLimit", UpperLimit),
new XElement("MeasuredValue", MeasuredValue))));
}
}
}
И код функции "isElementExist":
public bool doesElementExist(string rootName, string parentName,string childName, string nodeValue)
{
if (!firstEntry)
{
bool value = ictLog.Elements(rootName).Elements(parentName) //Get any item where the child value is the same as the specificed one (for some reason it works on reverse, returns false if found)
.Elements(childName)
.Any(x => x.Value == nodeValue);
return value;
}
else
return false;
}
Я установил флаг первой записи, если я не нашел файл в местоположении с расширением .xml.
Моя проблема заключается в том, что созданный XML-файл группируется в первый раз, как и следовало (использует второй формат, когда параметр даты совпадает с тем, который уже имеется в xml), но дублирует каждую запись. Если я вызываю функцию второй раз с другим заголовком, он правильно создает первый формат, но никогда не группирует, даже если запись уже существует (не применяется второй формат). Обратите внимание, что у меня такая же дата, но она не группировалась так, как должна. Пример вывода:
<FailReport>
<SystemDescription>
<SystemID>ICTT_0030</SystemID>
<ReportDate>May7,2014 18:44</ReportDate>
<SpecFile>xptofile.c</SpecFile>
<UUT>123</UUT>
<FailDescription>
<Tst1>tsts</Tst1>
<Tst2>tsts1</Tst2>
<TestType>type2</TestType>
<Component>cTst1</Component>
<LowerLimit>0.400</LowerLimit>
<UpperLimit>0.800</UpperLimit>
<MeasuredValue>O_RngV</MeasuredValue>
</FailDescription>
<FailDescription>
<Tst1>tsts</Tst1>
<Tst2>tsts1</Tst2>
<TestType>type2</TestType>
<Component>cTst1</Component>
<LowerLimit>0.900</LowerLimit>
<UpperLimit>0.700</UpperLimit>
<MeasuredValue>0.91</MeasuredValue>
</FailDescription>
<FailReport>
<SystemDescription>
<SystemID>ICTT_0030</SystemID>
<ReportDate>May7,2014 18:44</ReportDate>
<SpecFile>xptofile.c</SpecFile>
<UUT>123</UUT>
<FailDescription>
<Tst1>tsts</Tst1>
<Tst2>tsts1</Tst2>
<TestType>type2</TestType>
<Component>cTst1</Component>
<LowerLimit>0.400</LowerLimit>
<UpperLimit>0.800</UpperLimit>
<MeasuredValue>O_RngV</MeasuredValue>
</FailDescription>
<FailDescription>
<Tst1>tsts</Tst1>
<Tst2>tsts1</Tst2>
<TestType>type2</TestType>
<Component>cTst1</Component>
<LowerLimit>0.900</LowerLimit>
<UpperLimit>0.700</UpperLimit>
<MeasuredValue>0.91</MeasuredValue>
</FailDescription>
<SystemDescription>
<SystemID>lalalala</SystemID>
<ReportDate>May21,2014 11:59</ReportDate>
<SpecFile>filefile</SpecFile>
<UUT>111</UUT>
</SystemDescription>
<FailDescription>
<Tst1>TP1300-T[201]</Tst1>
<Tst2>Tst2002-G[1]</Tst2>
<TestType>Res</TestType>
<Component>R1301</Component>
<LowerLimit>9.9000K</LowerLimit>
<UpperLimit>13.000K</UpperLimit>
<MeasuredValue>13.089K</MeasuredValue>
</FailDescription>
</FailReport>
<FailReport>
<SystemDescription>
<SystemID>lalalala</SystemID>
<ReportDate>May21,2014 11:59</ReportDate>
<SpecFile>filefile</SpecFile>
<UUT>111</UUT>
</SystemDescription>
<FailDescription>
<Tst1>tsts11111</Tst1>
<Tst2>tssa9</Tst2>
<TestType>Res</TestType>
<Component>kkk</Component>
<LowerLimit>9.9000K</LowerLimit>
<UpperLimit>13.000K</UpperLimit>
<MeasuredValue>13.089K</MeasuredValue>
</FailDescription>
Извините за длинный пост, но я пытался документировать его как подробно, как я мог.
Примечание: У меня может быть более 2 записей во втором формате. –
В моем решении используется список, который может обрабатывать как один объект, так и несколько объектов. –
jdweng