I was creating a service that would generate and export the xml file from sql server db from a user stored procedure with WriteXml. It runs successfully, but I don't want the output xml file contains any xml attributes before the actual columns that I want. I've tried IgnoreSchema. But the first line xml version was still existed and I was trying to add space between columns.
The code:
public void TEST(string param)
{
List<Model> list = new List<Model>();
//this function is for access the db and get the data
DataSet ds = DAL.Function(param);
//Export as XML File
//ds.WriteXml(@"C:\Test\Test.XML", XmlWriteMode.WriteSchema);
}
The output looks like:
<?xml version = "1.0" standalone="yes"?>
<NewDataSet>
<Table>
<a> 005 </a>
<b> 1 </b>
</Table>
<Table>
<a> 006 </a>
<b> 2 </b>
</Table>
</NewDataSet>
But I want it looks like this with formatting:
<Table>
<a> 005 </a>
<b> 1 </b>
</Table>
<Table>
<a> 006 </a>
<b> 2 </b>
</Table>
First of all I will point out that well formed XML documents must have only one root element .
Under normal circumstances I would say you should not attempt to mess with System.Xml
namespace as it is going get very dirty. But let us for a second imagine we don't care about performance and maintainability, purely as a thought experiment of course. Then one way to approach your problem will be to modify XmlWriter
so it skips over your NewDataSet
tag:
class MyWriter : XmlTextWriter
{
private int Top // this is a pointer to top of internal stack that XmlWriter uses to determine closing tag correspondence
{
get
{
FieldInfo top = typeof(XmlTextWriter).GetField("top", BindingFlags.NonPublic | BindingFlags.Instance);
return (int)top.GetValue(this);
}
}
public MyWriter(string name, Encoding enc) : base(name, enc) {}
public override void WriteStartElement(string prefix, string localName, string ns)
{
if (localName == "NewDataSet") { // skip the tag
MethodInfo PushStack = typeof(XmlTextWriter).GetMethod("PushStack", BindingFlags.NonPublic | BindingFlags.Instance);
PushStack.Invoke(this, new object[] {}); // for internal state tracking to work, we still need to push the stack as if we wrote it out. we'll have to account for that later
return;
}
base.WriteStartElement(prefix, localName, ns);
}
public override void WriteEndElement()
{
if(Top <= 1) return; // do not attempt to write outermost tag, we already skipped it in the opening counterpart
base.WriteEndElement();
}
}
void Main()
{
//...your code here
var writer = new MyWriter(@"C:\Test\Test.XML", Encoding.UTF8); // instantiate your own writerm
ds.WriteXml(writer, XmlWriteMode.IgnoreSchema); // and use it instead of stock standard
}
as you can see, problem is, XmlWriter
does not expose some methods and properties required for this to work, so I had to use reflection to invoke them. Moreover, it makes it extremely hard to fetch some data structures by keeping them internal to class (as an exercise, try fetching TagInfo[] stack
field using the above technique and see what happens).
This however should give you the output you desire.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.