首页 > 解决方案 > 从数据库导出 XML 文件并在实际列之前获得没有任何属性的干净格式

问题描述

我正在创建一个服务,该服务将从使用 WriteXml 的用户存储过程中的 sql server db 生成和导出 xml 文件。它运行成功,但我不希望输出 xml 文件在我想要的实际列之前包含任何 xml 属性。我试过 IgnoreSchema。但是第一行 xml 版本仍然存在,我试图在列之间添加空格。

编码:

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);
}

输出如下所示:

<?xml version = "1.0" standalone="yes"?>
<NewDataSet>
  <Table>
    <a> 005 </a>
    <b> 1 </b>
  </Table>
  <Table>
    <a> 006 </a>
    <b> 2 </b>
  </Table>
</NewDataSet>

但我希望它看起来像这样的格式:

  <Table>
    <a> 005 </a>
    <b> 1 </b>
  </Table>

  <Table>
    <a> 006 </a>
    <b> 2 </b>
  </Table>

标签: c#asp.net.netsql-serverxml

解决方案


首先我要指出格式良好的 XML 文档必须只有一个根元素

在正常情况下,我会说你不应该尝试弄乱System.Xml命名空间,因为它会变得很脏。但是让我们再想象一下,我们并不关心性能和可维护性,当然,这纯粹是一个思想实验。然后解决您的问题的一种方法是进行修改XmlWriter,使其跳过您的NewDataSet标签:

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
}

正如您所看到的,问题是,XmlWriter它没有公开它工作所需的一些方法和属性,所以我不得不使用反射来调用它们。此外,通过将它们保留在类内部来获取某些数据结构变得非常困难(作为练习,尝试TagInfo[] stack使用上述技术获取字段,看看会发生什么)。

然而,这应该会给你你想要的输出。


推荐阅读