简体   繁体   English

使用LINQ编辑XML输出

[英]Editing XML Output With LINQ

I have an XML output file from a process being run that needs the contents of various fields edited according to a collection of tables in our database. 我有一个正在运行的进程的XML输出文件,它需要根据数据库中的表集合编辑的各个字段的内容。 For example, what's included in 例如,包括在内的内容

<?xml version="1.0" encoding="utf-8"?>
<ArrayOfUserReportPreviewListDto xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <UserReportPreviewListDto>
    <ExtensionData />
    <Id>previewReportFieldsId</Id>
    <Field0>-7</Field0>
    <Field1>L</Field1>
    <Field2>Lab Work Complete</Field2>
    <Field3>False</Field3>
    <Field4>LabWorkComplete</Field4>
    <Field6>False</Field6>
  </UserReportPreviewListDto>
  <UserReportPreviewListDto>
    <ExtensionData />
    <Id>previewReportFieldsId</Id>
    <Field0>-6</Field0>
    <Field1>S</Field1>
    <Field2>Sent to Lab</Field2>
    <Field3>False</Field3>
    <Field4>SentToLab</Field4>
    <Field6>False</Field6>
  </UserReportPreviewListDto>
  <UserReportPreviewListDto>
    <ExtensionData />
    <Id>previewReportFieldsId</Id>
    <Field0>-5</Field0>
    <Field1>V</Field1>
    <Field2>Void</Field2>
    <Field3>False</Field3>
    <Field4>Void</Field4>
    <Field6>True</Field6>
    <Field7>12/11/2013</Field7>
    <Field9>769</Field9>
  </UserReportPreviewListDto>

would need Field4 changed from LabWorkComplete (tblEnum.FieldTypeDesc) to 2 (tblEnum.FieldTypeNum). 需要将Field4从LabWorkComplete(tblEnum.FieldTypeDesc)更改为2(tblEnum.FieldTypeNum)。

I'm very new to using LINQ, and am not even completely sure it's the best route for this. 我对使用LINQ非常陌生,我甚至不确定它是最好的途径。 I've created a DataSet in the project, with a DataTable populated from the database with what I need to work with. 我在项目中创建了一个DataSet,其中DataTable是从数据库中填充的,我需要使用它。 And...that's as far as I've got. 而且......就我而言。 Right now I'm using a massive list of tedious If statements to accomplish this, and am thinking this avenue may be more efficient than a collection of statements like this. 现在我正在使用大量乏味的If语句来实现这一目标,并且我认为这种方法可能比这样的语句集合更有效。

var xe = XElement.Load("serializer.xml");
string field4Value = xe.XPathSelectElement(@"/UserReportPreviewListDto/Field4").Value;
if (field4Value == "Incomplete")
{
    xe.XPathSelectElement(@"/UserReportPreviewListDto/Field4").Value = "0";
}
    else if (field4Value == "SendToLab")
{
xe.XPathSelectElement(@"/UserReportPreviewListDto/Field4").Value = "1";
}
    else if (field4Value == "LabWorkComplete")
{
    xe.XPathSelectElement(@"/UserReportPreviewListDto/Field4").Value = "2";
}

So that's where I am. 所以我就是这样。 If LINQ wouldn't be the best avenue, what would be? 如果LINQ不是最好的途径,会是什么? If it would be, what would be the best way to do it? 如果是的话,最好的办法是什么? Additionally, any particularly helpful resources along these lines that can be recommended would be appreciated; 此外,可以推荐沿着这些线路推荐的任何特别有用的资源; I'd much rather learn code than copy code. 我更愿意学习代码而不是复制代码。 I'd hate to have to ask this again next week, after all. 毕竟,我不想在下周再问这个问题。

Your XML structure is weird. 你的XML结构很奇怪。 Field0...Field6 is not common, there are usually meaningful names in there. Field0...Field6并不常见,那里通常有有意义的名字。 You can always write a function that encapsulates string to integer string conversion, and just provide an xpath as an argument. 您总是可以编写一个将字符串封装到整数字符串转换的函数,并只提供一个xpath作为参数。 Then go higher level, provide xpath + conversion delegate, and from this point it's as easy as one line per property. 然后转到更高级别,提供xpath +转换委托,从这一点开始,就像每个属性一行一样简单。 Here is an implementation example: 这是一个实现示例:

using System;
using System.Xml.Linq;
using System.Xml.XPath;

namespace ConsoleApplication1
{
  class Program
  {
    static void Main(string[] args)
    {
      var xe = XElement.Load("serializer.xml");
      ConvertValue(xe, @"/UserReportPreviewListDto/Field4", TranslateValueField4);
    }

    private static void ConvertValue(XElement xe, string xpath, TranslateValue translator)
    {
      string field4Value = xe.XPathSelectElement(xpath).Value;
      xe.XPathSelectElement(xpath).Value = translator(field4Value);
    }

    private delegate string TranslateValue(string value);

    private static string TranslateValueField4(string value)
    {
      switch (value)
      {
        case "Incomplete" :
          return "0";
        case "SendToLab" :
          return "1";
        case "LabWorkComplete":
          return "2";
        default:
          throw new NotImplementedException(); //or provide handling for unknown values
      }
    }
  }
}

You can also avoid using xpath, and just iterate using foreach: 您也可以避免使用xpath,并使用foreach进行迭代:

static void Main(string[] args)
{
  var doc = XDocument.Load(@"input.xml");
  foreach (var xe in doc.Root.Elements("UserReportPreviewListDto"))
  {
    ConvertValue(xe, "Field4", TranslateValueField4);
  }
  //doc.Save(path);
}

private static void ConvertValue(XElement xe, string fieldName, TranslateValue translator)
{
  //.Element returns Nothing if element is missing, may want to handle this case
  XElement field4 = xe.Element(fieldName);
  string field4Converted = TranslateValueField4(field4.Value);
  field4.SetValue(field4Converted);
}

I always, always, always prefect to store xml into custom classes and then work with them inside my C# environment. 我始终总是将xml存储到自定义类中,然后在我的C#环境中使用它们。 Makes the process of modifying it feel much more natural. 使修改过程感觉更自然。 Please look at my question here to see the best way to do this. 请在这里查看我的问题,看看最好的方法。 It takes a bit more time, but it makes things SO much easier in the long run. 它需要更多的时间,但从长远来看,它使事情变得更加容易。 You said you wanted the best route and to learn, right? 你说你想要最好的路线和学习,对吗? ;) ;)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM