如何在使用override void WriteEndElement()时使用XmlWriterSettings()?

sap*_*ket 10 c# xml serialization

我正在使用不导入缩写的空xml元素的遗留应用程序.例如:

坏空:

<foo />
Run Code Online (Sandbox Code Playgroud)

好空:

<foo></foo>
Run Code Online (Sandbox Code Playgroud)

我知道实现这一目标的解决方案,我现在将介绍:

public class XmlTextWriterFull : XmlTextWriter
{


    public XmlTextWriterFull(Stream stream, Encoding enc) : base(stream, enc)
    {
    }

    public XmlTextWriterFull(String str, Encoding enc) : base(str, enc) 
    {
    }

    public override void WriteEndElement()
    {
        base.WriteFullEndElement();
    }
}
Run Code Online (Sandbox Code Playgroud)

和客户端代码:

                    var x_settings = new XmlWriterSettings();
                    x_settings.NewLineChars = Environment.NewLine;
                    x_settings.NewLineOnAttributes = true;
                    x_settings.NewLineHandling = NewLineHandling.Replace;
                    x_settings.CloseOutput = true;
                    x_settings.Indent = true;
                    x_settings.NewLineOnAttributes = true;

                    //var memOut = new MemoryStream();
                    var writer = new XmlTextWriterFull(outputFilename, Encoding.UTF8); //Or the encoding of your choice
                    var x_serial = new XmlSerializer(typeof(YOUR_OBJECT_TYPE));
                    x_serial.Serialize(writer, YOUR_OBJECT_INSTANCE);

                    writer.Close();
Run Code Online (Sandbox Code Playgroud)

但是,如果您仔细观察,XmlWriterSettings则从未在客户端代码中使用过.因此xml输出格式非常复杂.我的问题是这样的:我如何调整上面的代码来接受XmlWriterSettings

工厂创建方法和密封/内部/抽象类的使用使得难以实现覆盖.

我会接受另一种解决方案,我不同意上述解决方案.

  • 解决方案

第1步:在解决方案中创建以下类:

public class XmlTextWriterFull : XmlTextWriter
{
    public XmlTextWriterFull(TextWriter sink) : base(sink)
    {
        Formatting = Formatting.Indented;
    }

    public override void WriteEndElement()
    {
        base.WriteFullEndElement();
    }
}
Run Code Online (Sandbox Code Playgroud)

第2步:添加以下客户端代码.确保将YOUR_OBJECT_TYPE和YOUR_OBJECT_INSTANCE替换为您正在使用的类和实例:

TextWriter streamWriter = new StreamWriter(outputFilename);
var writer = new XmlTextWriterFull(streamWriter);

var x_serial = new XmlSerializer(typeof (YOUR_OBJECT_TYPE));
x_serial.Serialize(writer, YOUR_OBJECT_INSTANCE);

writer.Close();
Run Code Online (Sandbox Code Playgroud)

上面的解决方法将产生以下空xml元素格式:

<foo>
</foo>
Run Code Online (Sandbox Code Playgroud)

此解决方法的问题是它添加换行符(请注意元素在单独的行上).这可能是您可以接受的,但会导致遗留应用程序出现问题.

nic*_*k_w 5

这个怎么样.

XmlWrappingWriterhttp://www.tkachenko.com/blog/archives/000585.html获取了很棒的课程(为了简洁起见,我省略了代码).

有了它,我们可以创建一个子类如下(非常类似于你原来的子类):

public class XmlTextWriterFull2 : XmlWrappingWriter
{
    public XmlTextWriterFull2(XmlWriter baseWriter)
        : base(baseWriter)
    {
    }

    public override void WriteEndElement()
    {
        base.WriteFullEndElement();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后可以像这样调用它(再次非常相似):

var x_settings = new XmlWriterSettings();
x_settings.NewLineChars = Environment.NewLine;
x_settings.NewLineOnAttributes = true;
x_settings.NewLineHandling = NewLineHandling.None;
x_settings.CloseOutput = true;
x_settings.Indent = true;
x_settings.NewLineOnAttributes = true;

using (XmlWriter writer = XmlWriter.Create(outputFilename, x_settings))
{
    using (XmlTextWriterFull2 xmlTextWriterFull = new XmlTextWriterFull2(writer))
    {
        var x_serial = new XmlSerializer(typeof(YOUR_OBJECT_TYPE));
        x_serial.Serialize(xmlTextWriterFull, YOUR_OBJECT_INSTANCE);
    }
}
Run Code Online (Sandbox Code Playgroud)

在我的例子中,一个先前被渲染为的元素

<Foo>
</Foo>
Run Code Online (Sandbox Code Playgroud)

成为

<Foo></Foo>
Run Code Online (Sandbox Code Playgroud)

正如你在问题中提到的那样,这实际上是一个非常棘手的问题,因为所有东西都被密封/内部等,使得覆盖相当困难.我认为我最大的问题是试图XmlWriter接受XmlWriterSettings:除了这种方法,我找不到让原件XmlTextWriterFull尊重给定的方法XmlWriterSettings.

MSDN声明这种方法:

XmlWriter.Create(XmlWriter, XmlWriterSettings)
Run Code Online (Sandbox Code Playgroud)

可用于应用XmlWriterSettingsXmlWriter.我不能像我想的那样工作(缩进从未工作过,例如),并且在反编译代码时,似乎没有所有设置都与这个特定方法一起使用,因此我的调用代码只是传入在outputFile(某种流将工作一样好).