2015-05-27 3 views
0

Я пытаюсь создать файл 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) 

В этой функции мне нужно сделать несколько вещей:

  1. Если Xml не существует в местоположении, мне нужно его создать и заполнить;
  2. Если он существует, загрузите файл и отредактируйте его;
  3. Если где-то в файле Xml уже существует запись типа «May7,2014 18:44», примените второй формат (сохраните «header», который является «SystemDescription», но добавьте второй/третий/wtv «FailDescription», блок с различными параметрами для «Test1», «Test2» и так далее
  4. Если он не существует использовать первый формат и создать «новый блок»

Это код, у меня есть атм..:

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> 

Извините за длинный пост, но я пытался документировать его как подробно, как я мог.

+0

Примечание: У меня может быть более 2 записей во втором формате. –

+0

В моем решении используется список , который может обрабатывать как один объект, так и несколько объектов. – jdweng

ответ

0

Я бы сделал это с помощью сериализации. См. Код ниже для написания и чтения XML

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Xml; 
using System.Xml.Serialization; 
using System.IO; 

namespace ConsoleApplication30 
{ 
    class Program 
    { 
     const string FILENAME = @"c:\temp\Test.xml"; 
     static void Main(string[] args) 
     { 
      FailReport failReport = new FailReport(){ 
       systemDescription = new SystemDescription(){ 
         systemID = "system1", 
         reportDate = DateTime.Today, 
         specFile = "file1", 
         uut = "unit1" 
        }, 
       failDescriptions = new List<FailDescription>(){ 
        new FailDescription{ 
         test1 = "tst1", 
         test2 = "tst2", 
         testType = "typ1", 
         component = "cmp1", 
         lowerLimit = "llimit", 
         upperLimit = "ulimit", 
         measuredValue = "value" 
        }, 
        new FailDescription(){ 
         test1 = "tst3", 
         test2 = "tst4", 
         testType = "typ2", 
         component = "cmp2", 
         lowerLimit = "llimit3", 
         upperLimit = "ulimit4", 
         measuredValue = "value1" 
        } 
       } 
      }; 
      XmlSerializer serializer = new XmlSerializer(typeof(FailReport)); 

      StreamWriter writer = new StreamWriter(FILENAME); 
      XmlSerializerNamespaces _ns = new XmlSerializerNamespaces(); 
      _ns.Add("", ""); 
      serializer.Serialize(writer, failReport, _ns); 
      writer.Flush(); 
      writer.Close(); 
      writer.Dispose(); 

      XmlSerializer xs = new XmlSerializer(typeof(FailReport)); 
      XmlTextReader reader = new XmlTextReader(FILENAME); 
      FailReport newFailReport = (FailReport)xs.Deserialize(reader); 

     } 
    } 
    [XmlRoot("FailReport")] 
    public class FailReport 
    { 
     [XmlElement("")] 
     public SystemDescription systemDescription {get;set;} 
     [XmlElement("")] 
     public List<FailDescription> failDescriptions {get;set;} 
    } 
    [XmlRoot("SystemDescription")] 
    public class SystemDescription 
    { 
     [XmlElement("")] 
     public string systemID {get;set;} 
     [XmlElement("")] 
     public DateTime reportDate {get;set;} 
     [XmlElement("")] 
     public string specFile {get;set;} 
     [XmlElement("")] 
     public string uut {get;set;} 

    } 
    [XmlRoot("FailDescription")] 
    public class FailDescription 
    { 
     [XmlElement("Test1")] 
     public string test1 {get;set;} 
     [XmlElement("Test2")] 
     public string test2 {get;set;} 
     [XmlElement("TestType")] 
     public string testType {get;set;} 
     [XmlElement("Component")] 
     public string component {get;set;} 
     [XmlElement("LowerLimit")] 
     public string lowerLimit {get;set;} 
     [XmlElement("UpperLimit")] 
     public string upperLimit {get;set;} 
     [XmlElement("MeasuredValue")] 
     public string measuredValue {get;set;} 
    } 
} 
Смежные вопросы