简体   繁体   中英

Exported XML file from Database and get clean format without any attributes before actual columns

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM