【问题标题】:Add nodes and grouping添加节点和分组
【发布时间】:2015-05-27 16:08:25
【问题描述】:

我正在尝试基于从我的计算机本地读取的文件使用 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 文件中的某处已存在类似“May7,2014 18:44”的条目,则应用第二种格式(保留“标题”即“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))));
                    }
                }          
        }

而函数“doesElementExist”的代码如下:

 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>

抱歉,这篇文章太长了,但我尽量详细地记录下来。

【问题讨论】:

  • 注意:第二种格式可以有两个以上的条目。
  • 我的解决方案使用 List 可以处理单个对象或多个对象。

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


【解决方案1】:

我会使用序列化来做到这一点。请参阅下面的代码来编写和读取 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;}
    }
}

【讨论】:

    猜你喜欢
    • 2020-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-16
    相关资源
    最近更新 更多