I can read and write a XML File into a Dataset with no problems, but if I save the DataSet with ds.WriteXml("Testdata.xml")开发者_Go百科
a additional Tag <NewDataSet>.......</NewDataSet>
is generrated.
Is it possible to supress this Tag genaration?
A dataset can contain multiple tables and a valid XML file must contain a single root node that's why it is wrapped in this node. You could specify the name of the root node when creating the DataSet:
var ds = new DataSet("root");
but if you want to remove it you could first load the DataSet into a XDocument or XmlDocument and then extract the node you need and save it into a file.
I was looking to do the same thing in order to stream serialized DataRows without the overhead of tables and such. My solution was to use a temp DataTable as a sort of buffer which I fill with DataRows in chunks and then generate XML that I append to a stream. In order to reuse DataTable.WriteXml I had to solve the same problem and I wanted it to be efficient.
What I opted for is to create my own custom XmlWriter which is a lot simpler than it sounds. It works by skipping over elements that meet the condidtion of a predicate. In this case the predicate is whether the element name is the same as the expected DataSet name.
var writer = new RootlessDataSetXmlWriter(
File.OpenWrite(@"C:\temp\ds.xml")
"YourDataSetName");
dataSet.WriteXml(writer, XmlWriteMode.IgnoreSchema);
writer.Flush();
writer.Close();
Below is the implementation for RootlessDataSetXmlWriter and the ELementSkippingXmlWritter base class.
public class RootlessDataSetXmlWriter : ElementSkippingXmlWriter
{
private string _dataSetName;
public RootlessDataSetXmlWriter(Stream stream, string dataSetName)
: base(stream, (e) => string.Equals(e, dataSetName, StringComparison.OrdinalIgnoreCase))
{
_dataSetName = dataSetName;
this.Formatting = System.Xml.Formatting.Indented;
}
}
public class ElementSkippingXmlWriter : XmlTextWriter
{
private Predicate<string> _elementFilter;
private int _currentElementDepth;
private Stack<int> _sightedElementDepths;
public ElementSkippingXmlWriter(Stream stream, Predicate<string> elementFilter)
: base(stream, Encoding.UTF8)
{
_elementFilter = elementFilter;
_sightedElementDepths = new Stack<int>();
}
public override void WriteStartElement(string prefix, string localName, string ns)
{
if (_elementFilter(localName))
{
// Skip the root elements
_sightedElementDepths.Push(_currentElementDepth);
}
else
{
base.WriteStartElement(prefix, localName, ns);
}
_currentElementDepth++;
}
public override void WriteEndElement()
{
_currentElementDepth--;
if (_sightedElementDepths.Count > 0 && _sightedElementDepths.Peek() == _currentElementDepth)
{
_sightedElementDepths.Pop();
return;
}
base.WriteEndElement();
}
}
For those "efficient" like me, here are the simple XDocument and XmlDocument codez (live examples at https://dotnetfiddle.net/s2VP0k). Though XmlDocument was typically faster in my simple tests, I prefer the XDocument's simplicity.
XDocument:
return System.Xml.Linq.XElement
.Parse(xmlString)
.FirstNode
.ToString(); // <c><a>123</a></c>
XmlDocument:
var xmlDoc = new System.Xml.XmlDocument();
xmlDoc.LoadXml(xmlString);
return xmlDoc.DocumentElement.InnerXml; // <c><a>123</a></c>
精彩评论