More people complained about that the result of the Lists.GetListItems method call does not contain the empty fields, so the resulting XML cannot be load into a DataSet:
http://social.msdn.microsoft.com/Forums/en-US/sharepointdevelopment/thread/95855246-b8f8-4dda-897a-c4480cc74044/#0a2d42ed-7365-413c-a12f-ccbf95025c12
http://www.tech-archive.net/Archive/SharePoint/microsoft.public.sharepoint.portalserver.development/2006-09/msg00056.html
A dirty workaround for that issue may be to adding the missing attributes to the XML from code before trying to load into the DataSet.
In the following code I illustrate this approach. In this code I first get the columns of the default view of the list using the List.GetListAndView method, then retrive the data using the Lists.GetListItems method, iterate through all the rows and columns, and if an attribute is missing for a column, add an empty attribute.
String listName = "YourListName";
listService.Credentials = new NetworkCredential("user", "password", "domain");
XmlNamespaceManager nsmgr;
// get info about the default view
// the 2nd parameter is null -> it is the default view
XmlNode listView = listService.GetListAndView(listName, null);
nsmgr = new XmlNamespaceManager(listView.OwnerDocument.NameTable);
nsmgr.AddNamespace("a", "http://schemas.microsoft.com/sharepoint/soap/");
List<String> fieldNames = new List<string>();
foreach (XmlNode field in listView.SelectNodes("a:List/a:Fields/a:Field", nsmgr))
{
XmlAttribute attr = field.Attributes["Name"];
// it should not be null, but we check it
if (attr != null)
{
// we store all fields in a collection for later use
fieldNames.Add(attr.Value);
}
}
// get data from list
XmlNode items = listService.GetListItems(listName, null, null, null, null, null, null);
nsmgr = new XmlNamespaceManager(items.OwnerDocument.NameTable);
nsmgr.AddNamespace("z", "#RowsetSchema");
nsmgr.AddNamespace("rs", "urn:schemas-microsoft-com:rowset");
XmlNodeList itemNodeList = items.SelectNodes("rs:data/z:row", nsmgr);
foreach(XmlNode itemNode in itemNodeList)
{
foreach (String fieldName in fieldNames)
{
String wsFieldName = "ows_" + fieldName;
XmlAttribute attr = itemNode.Attributes[wsFieldName];
// if the attribute is missing, we should add it
if (attr == null)
{
attr = itemNode.OwnerDocument.CreateAttribute(wsFieldName);
itemNode.Attributes.Append(attr);
}
}
}
DataSet listDataSet = new DataSet();
// read the result into a data set
XmlTextReader readerListDataSet = new XmlTextReader(items.OuterXml, XmlNodeType.Document, null);
listDataSet.ReadXml(readerListDataSet);
After this kind of preparation of XML it can be loaded into the DataSet.
You should know that this approach may not scale and perform well in case of a large amount of data, and I consider it a dirty workaround, but I don't know currently other solution for this request.