2014-12-05 55 views
3

我有一個來自正在運行的進程的XML輸出文件,它需要根據我們數據庫中的一系列表格編輯的各個字段的內容。例如,什麼是包含在使用LINQ編輯XML輸出

<?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> 

需要字段4從LabWorkComplete(tblEnum.FieldTypeDesc)改爲2(tblEnum.FieldTypeNum)。

我對使用LINQ很陌生,甚至沒有完全確定它是最好的路線。我已經在項目中創建了一個DataSet,其中一個DataTable從數據庫中填充了我需要處理的內容。而且......就我所知。現在我正在使用一大堆繁瑣的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"; 
} 

所以那就是我的位置。如果LINQ不是最好的途徑,那會是什麼?如果是的話,最好的辦法是什麼?此外,可以推薦使用這些方面的任何特別有用的資源,我寧願學習代碼而不是複製代碼。畢竟,我不想在下週再次問這個問題。

回答

1

您的XML結構很奇怪。 Field0...Field6不常見,通常有有意義的名字。你總是可以編寫一個將字符串封裝爲整數字符串轉換的函數,並提供一個xpath作爲參數。然後進入更高層次,提供xpath +轉換委託,從這一點開始,它就像每個屬性一行一樣簡單。下面是一個實現的例子:

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

您還可以避免使用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); 
} 
+0

這很奇怪,是的。但它是由客戶提供給我們的,那麼你能做什麼,呃? 你有什麼建議的代碼示例嗎?我想它並不像聽起來那麼複雜,但看到它寫出來會是巨大的幫助。 – Eiketsu 2014-12-05 17:27:17

+1

@Eiketsu:檢查我的答案(編輯包含代碼示例)。 – Neolisk 2014-12-05 18:33:39

+0

是否有一個可行的foreach語句可用於XML文件中的多個記錄,放置在xe的位置下方以循環訪問ConvertValue?是否有任何理由我不需要包含一個? – Eiketsu 2014-12-05 19:14:44

0

我永遠,永遠,永遠知府XML存儲到自定義類,然後一起工作他們在我的C#環境中。使修改過程感覺更自然。請看我的問題here以查看執行此操作的最佳方法。它需要更多時間,但從長遠來看,這使得事情變得更容易。你說你想要最好的路線和學習,對吧? ;)

+0

這種方法永遠不會在企業環境中工作。 :)在某些時候,您將需要手動處理所有序列化。特別是如果在序列化邏輯中有分支,即如果this,那麼field5是一個整數,並存儲在propertyX中,否則如果field6是日期,則屬性Y等等。如果處理依賴於其他字段,即如果field5是this,則會更糟。 field6是磁盤上的一個路徑,因此如果field5是這樣的,則需要打開一個文件,而field6是FTP上的路徑,則需要field7和field8中的證書。 – Neolisk 2014-12-05 18:24:19

+0

這是一個很好的方法,Volearix,我很欣賞這個建議,但@Neilisk提出了一個很好的觀點。根據該計劃將運行的報告的主要表格,這將最終需要進一步改變事情。那麼,我現在在做什麼的Field4(「Type」)可能在下一個報告中有所不同(例如「CreationDate」)。所以這會增加另一層級的複雜性,看起來你的系統可能有困難(如果我正確理解它的話)。這是我認爲LINQ可能要走的另一個原因,但仍然不確定。 – Eiketsu 2014-12-05 18:32:28