一个艰难的表转换为XML

时间:2009-11-07 14:04:00

标签: c# xml datatable .net-2.0

我有一个DataTable,我从数据库中选择(好吧,这些数据跨越几个表,查询后放入DataTable,它显示在下面)

ColumnA ColumnB
a 11
b 33
b 44
a 22
b 55

但我希望将其转换为像这样的XML

<root>
   <header name ='a'>
       <item name='11' />
       <item name='22' />
   </header>
   <header name ='b'>
       <item name='33' />
       <item name='44' />
       <item name='55' />
   </header>

</root>

C#是否有一种简单的方法来实现它?

4 个答案:

答案 0 :(得分:5)

为什么要打扰C#?您可以直接在T-SQL中执行此操作(SQL Server 2005及更高版本):

SELECT 
    ColumnA AS '@name',
    (SELECT ColumnB AS '@name' 
     FROM YourTable t 
     WHERE t.ColumnA = YourTable.ColumnA 
     FOR XML PATH('item'), TYPE)
FROM 
    YourTable
GROUP BY
    ColumnA
FOR XML PATH('header'), ROOT('root')

给你:

<root>
  <header name="a">
    <item name="11" />
    <item name="22" />
  </header>
  <header name="b">
    <item name="33" />
    <item name="44" />
    <item name="55" />
  </header>
</root>

您可以使用标准ADO.NET SqlCommand执行此SQL查询,并获取已经格式化的XML。

马克

答案 1 :(得分:2)

使用LINQ: -

var qry = from row in Table
          group row by row.ColumnA into header
          select header;

var elem = new XElement("root");

foreach (var header in qry)
{
  var elemHead = new XElement("header", new XAttribute("name", header.Key));
  elem.Add(elemHead);
  foreach (var item in header)
    elemHead.Add(new XElement("item", new XAttribute("name", item.ColumnB)));
}
// the variable elem contains the result.

答案 2 :(得分:2)

好的,第二种方法是在DataTable开始学习数据后可用。

代码更复杂,因为基于DataTable,你在分组等方面做得不够。我正在构建XmlDocument(因为你在.NET 2.0上)同时扫描数据行。我需要跟踪字典中的<header>元素,以便为文档中已存在的XmlElement添加具有相同“ColumnA”值的第二个,第三个条目 - 它有点涉及,但是如果你仔细研究它,我希望你看到它真的没有任何诡计或任何东西 - 只需要在构建XmlDocument的过程中进行一些记账:

// create the XmlDocument and add <root> node
XmlDocument doc = new XmlDocument();
doc.AppendChild(doc.CreateElement("root"));

// dictionary to keep track of <header> nodes
Dictionary<string, XmlNode> nodesPerColumnA = new Dictionary<string, XmlNode>();

// Loop through data rows
foreach (DataRow row in tbl.Rows)
{
   // extract values for ColumnA and ColumnB as strings
   string columnAValue = row["ColumnA"].ToString();
   string columnBValue = row["ColumnB"].ToString();

   // create a new <item> XmlNode and fill its attribute @Name 
   XmlElement newNode = doc.CreateElement("item");

   XmlAttribute newNodeAttribute = doc.CreateAttribute("name");
   newNodeAttribute.InnerText = columnBValue;

   newNode.Attributes.Append(newNodeAttribute);

   // check if we already have a <header> node for that "ColumnA" value
   if(nodesPerColumnA.ContainsKey(columnAValue))
   {
       // if so - just add <item> below that <header>
       XmlNode parent = nodesPerColumnA[columnAValue];

       parent.AppendChild(newNode);
   }
   else
   {
       // if not - create appropriate <header> node and its @name attribute
       XmlElement header = doc.CreateElement("header");

       XmlAttribute headerAttr = doc.CreateAttribute("name");
       headerAttr.InnerText = columnAValue;

       header.Attributes.Append(headerAttr);

       header.AppendChild(newNode);

       doc.DocumentElement.AppendChild(header);

       // store that <header> xmlnode into the dictionary for future use
       nodesPerColumnA.Add(columnAValue, header);
    }
 }

 // check the contents of the XmlDocument at the end
 string xmlContents = doc.InnerXml;

答案 3 :(得分:-1)

这将使用.NET 3.5和XDocument

来实现
XDocument yourDocument = new XDocument(new XElement("root",
    new XElement("header",
        new XAttribute("name", "a"),
        new XElement("item",
            new XAttribute("name", "11")),
        new XElement("item",
            new XAttribute("name", "22"))),
    new XElement("header",
        new XAttribute("name", "b"),
        new XElement("item",
            new XAttribute("name", "33")),
        new XElement("item",
            new XAttribute("name", "44")),
        new XElement("item",
            new XAttribute("name", "55")))));