2010-05-19 45 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);