我有一个包含对象集合的XML文档。每个对象都有一个键/值对的标签和值。我试图将其转换为DataSet,但是当我执行ds.ReadXml(xmlFile)时,它会创建两列:label和value。
我想要的是为每个“标签”添加一列,并将该值作为该行的一部分。这是我的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>John@Doe.com</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>John2@Doe.com</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>John3@Doe.com</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>John4@Doe.com</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行将是: John,John @ Doe.com,http://domain1.com,999-999-9999,Earth,Misc,True
如何使用提供的XML执行此操作?
答案 0 :(得分:1)
您必须转换数据才能按照自己的方式使用它。如你所见,你的结构很糟糕。
我建议您在Visual Studio中创建一个空数据集(来自Add-&gt; 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; }
}
答案 1 :(得分:0)
我将遍历XML并根据您的迭代方式(Linq最灵活),创建一个新对象(例如,数据表),并以您需要的方式描述您的数据。
答案 2 :(得分: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);