2010-05-19 188 views
1

我有一個具有對象集合的XML文檔。每個對象都有一個標籤和值的鍵/值對。我試圖將其轉換爲DataSet,但是當我執行ds.ReadXml(xmlFile)時,它會創建兩列:標籤和值。如何將多對一的XML數據轉換爲數據集?

我想要的是每個「標籤」的列和要成爲行的一部分的值。這裏是我的XML的示例:

<responses> 
    <response> 
    <properties id="1" Form="Account Request" Date="Tuesday, March 16, 2010 5:04:26 PM" Confirmation="True" /> 
    <fields> 
     <field> 
     <label>Name</label> 
     <value>John</value> 
     </field> 
     <field> 
     <label>Email</label> 
     <value>[email protected]</value> 
     </field> 
     <field> 
     <label>Website</label> 
     <value>http://domain1.com</value> 
     </field> 
     <field> 
     <label>Phone</label> 
     <value>999-999-9999</value> 
     </field> 
     <field> 
     <label>Place of Birth</label> 
     <value>Earth</value> 
     </field> 
     <field> 
     <label>Misc</label> 
     <value>Misc</value> 
     </field> 
     <field> 
     <label>Comments</label> 
     <value /> 
     </field> 
     <field> 
     <label>Agree to Terms?</label> 
     <value>True</value> 
     </field> 
    </fields> 
    </response> 
    <response> 
    <properties id="2" Form="Account Request" Date="Tuesday, March 17, 2010 5:04:26 PM" Confirmation="True" /> 
    <fields> 
     <field> 
     <label>Name</label> 
     <value>John2</value> 
     </field> 
     <field> 
     <label>Email</label> 
     <value>[email protected]</value> 
     </field> 
     <field> 
     <label>Website</label> 
     <value>http://domain2.com</value> 
     </field> 
     <field> 
     <label>Phone</label> 
     <value>999-999-9999</value> 
     </field> 
     <field> 
     <label>Place of Birth</label> 
     <value>Earth</value> 
     </field> 
     <field> 
     <label>Misc</label> 
     <value>Misc</value> 
     </field> 
     <field> 
     <label>Comments</label> 
     <value /> 
     </field> 
     <field> 
     <label>Agree to Terms?</label> 
     <value>True</value> 
     </field> 
    </fields> 
    </response> 
    <response> 
    <properties id="3" Form="Account Request" Date="Tuesday, March 18, 2010 5:04:26 PM" Confirmation="True" /> 
    <fields> 
     <field> 
     <label>Name</label> 
     <value>John3</value> 
     </field> 
     <field> 
     <label>Email</label> 
     <value>[email protected]</value> 
     </field> 
     <field> 
     <label>Website</label> 
     <value>http://domain3.com</value> 
     </field> 
     <field> 
     <label>Phone</label> 
     <value>999-999-9999</value> 
     </field> 
     <field> 
     <label>Place of Birth</label> 
     <value>Earth</value> 
     </field> 
     <field> 
     <label>Misc</label> 
     <value>Misc</value> 
     </field> 
     <field> 
     <label>Comments</label> 
     <value /> 
     </field> 
     <field> 
     <label>Agree to Terms?</label> 
     <value>True</value> 
     </field> 
    </fields> 
    </response> 
    <response> 
    <properties id="4" Form="Account Request" Date="Tuesday, March 19, 2010 5:04:26 PM" Confirmation="True" /> 
    <fields> 
     <field> 
     <label>Name</label> 
     <value>John</value> 
     </field> 
     <field> 
     <label>Email</label> 
     <value>[email protected]</value> 
     </field> 
     <field> 
     <label>Website</label> 
     <value>http://domain4.com</value> 
     </field> 
     <field> 
     <label>Phone</label> 
     <value>999-999-9999</value> 
     </field> 
     <field> 
     <label>Place of Birth</label> 
     <value>Earth</value> 
     </field> 
     <field> 
     <label>Misc</label> 
     <value>Misc</value> 
     </field> 
     <field> 
     <label>Comments</label> 
     <value /> 
     </field> 
     <field> 
     <label>Agree to Terms?</label> 
     <value>True</value> 
     </field> 
    </fields> 
    </response> 
</responses> 

如何將其轉換爲一個DataSet,以便我可以列將其加載到一個GridView:姓名,電子郵件,網站,電話,出生地,雜項,評論,並同意條款?

然後第1行應該是: 約翰,[email protected]http://domain1.com,999-999-9999,地球,雜項,真正

我怎麼能做到這一點與XML提供的?

回答

1

你將不得不改變你的數據,以便按你想要的方式使用它。正如你所看到的,你有一個糟糕的結構。

我建議您在Visual Studio中創建一個空數據集(從Add-> New Item),然後將其設置爲您希望的樣子。編寫一些代碼以添加一些測試數據,然後使用DataSet.WriteXml將其寫入文件。這會告訴你你提出的結構會是什麼樣子。

然後,我建議您使用LINQ to XML將輸入XML轉換爲新格式。


下面是使用LINQ to XML來改變你的數據的例子:

public static void TransformIt(TextWriter output) 
{ 
    var inputDocument = XDocument.Parse(INPUT_XML); 
    if (inputDocument.Root == null) 
    { 
     return; 
    } 

    var doc = new XDocument(
     new XElement(
      "responses", 
      from response in inputDocument.Root.Elements() 
      select new XElement(
       "response", 
       from lv in GetResponseLabels(response) 
       select MakeResponse(lv.Label, lv.Value)))); 

    var settings = new XmlWriterSettings 
    { 
     Encoding = Encoding.UTF8, 
     Indent = true, 
    }; 
    using (var writer = XmlWriter.Create(output, settings)) 
    { 
     if (writer == null) 
     { 
      return; 
     } 

     doc.WriteTo(writer); 
    } 
} 

private static XElement MakeResponse(string label, string value) 
{ 
    var trimmedLabel = label.Replace(" ", String.Empty).Replace("?", String.Empty); 
    return new XElement(trimmedLabel, value); 
} 

private static IEnumerable<LabelAndValue> GetResponseLabels(XContainer response) 
{ 
    var fieldsElement = response.Element("fields"); 
    if (fieldsElement == null) 
    { 
     return null; 
    } 

    return from field in fieldsElement.Elements("field") 
      let valueElement = field.Element("value") 
      let labelElement = field.Element("label") 
      select new LabelAndValue 
      { 
       Label = labelElement == null ? "Unknown" : labelElement.Value, 
       Value = valueElement == null ? null : valueElement.Value 
      }; 
} 

private struct LabelAndValue 
{ 
    public string Label { get; set; } 
    public string Value { get; set; } 
} 
0

我將通過XML迭代並取決於你如何遍歷(LINQ是最靈活的),創建一個新的對象(例如數據表),以您需要的方式描述您的數據。

0

最終我改變做法了一下,這樣做(支點):

DataRow dr = dt.NewRow(); 

//TRANSFORM RESPONSE LABELS INTO COLUMNS 
foreach (XmlNode fieldNode in currentXml.SelectNodes("response/fields/field")) 
{ 
    string label = fieldNode.SelectSingleNode("label").InnerText ?? "Unknown"; 
    string value = fieldNode.SelectSingleNode("value").InnerText; 
    //CHECK IF ARBITRARY LABEL WAS ADDED BEFORE 
    if (!dt.Columns.Contains(label)) 
    { 
     //CREATE COLUMN FOR NEW LABEL 
     dt.Columns.Add(label); 
    } 
    dr[label] = value; 
} 
dt.Rows.Add(dr); 
} 
ds.Tables.Add(dt);