添加节点并对

时间:2015-05-27 16:08:25

标签: c# xml linq linq-to-xml element

我正在尝试使用XDocument和LINQ构建一个Xml文件,该文件基于从我的计算机本地读取的文件。 这似乎很容易(而且确实如此),直到我想要处理具体的事情。

所以,我希望我的代码支持这种格式

<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文件中的某个位置已经存在这样的条目&#34; May7,2014 18:44&#34;应用第二种格式(保留&#34;标题&#34;即#34; SystemDescription&#34;但添加第二/第三/ wtv&#34; FailDescription&#34;使用不同参数的块#34 ; Test1&#34;,&#34; Test2&#34;依此类推。
  4. 如果它不存在,请使用第一种格式并创建一个&#34;全新的块&#34;。
  5. 这是我的代码:

     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))));
                        }
                    }          
            }
    

    功能&#34; doElementExist&#34;代码如下:

     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>
    

    很抱歉这篇文章很长,但我试着尽可能详细地记录下来。

1 个答案:

答案 0 :(得分: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;}
    }
}