如何在另一个内部使用XmlWriter?

时间:2013-04-05 13:49:47

标签: c# .net xml xmlwriter

我正在尝试解决与How to check name of element with WriteEndElement

中描述的类似问题

我用内部和外部XmlWriter编写了这段代码。我们的想法是关闭内部XmlWriter也将关闭由不完全可靠的第三方库悬挂的任何标签。

var sb = new StringWriter();

using (var xml = XmlWriter.Create(sb, new XmlWriterSettings(){Indent = true}))
{
    xml.WriteStartElement("root");

    using (var inner = XmlWriter.Create(xml))
    {
        inner.WriteStartElement("payload1");

        // simulate ThirdPartyLibrary.Serialise(results, inner) leaving a tag open
        inner.WriteStartElement("third-party-stuff");
    }

    xml.WriteStartElement("payload2");
}

sb.ToString().Dump();

我希望这能产生

<root>
  <payload1>
    <third-party-stuff />
  </payload1>
  <payload2 />
</root>

但是我应该在应该写<payload2>

的行上遇到运行时错误
  

出现InvalidOperationException
  Writer已关闭或处于错误状态。

为什么会出现此错误?我没想到关闭内部的XmlWriter来关闭外部的。

2 个答案:

答案 0 :(得分:2)

在代码示例中使用变量名称关闭XmlWriter内部将释放(外部)XmlWriter xml。这是预期的行为,根据this MSDN条目处理XmlWriter“释放当前XmlWriter类实例使用的所有资源”,即它将释放它创建的任何“外部”XMLWriter。

此类代码将生成代码分析错误CA2202。以下link描述了解决此类情况的方法。

答案 1 :(得分:1)

查看从XmlWriter创建另一个xml时会发生什么:

static void Main(string[] args)
{
    var sb = new StringWriter();
    using (var xml = XmlWriter.Create(sb, new XmlWriterSettings() { Indent = true }))
    {
        xml.WriteStartElement("root");
        using (var inner = XmlWriter.Create(xml))
        {
            Debug.WriteLine(Object.ReferenceEquals(xml, inner));
            //UH OH! Returns true
            inner.WriteStartElement("payload1");
            // simulate ThirdPartyLibrary.Serialise(results, inner) leaving a tag open
            inner.WriteStartElement("third-party-stuff");
        }
        xml.WriteStartElement("payload2");
    }
    sb.ToString().Dump();
}

请参阅?因此,当您处置inner时,实际上是处置xml,因为它们是同一个对象。

如果您查看MSDN :( http://msdn.microsoft.com/en-us/library/77t6e4w3.aspx

  

返回值类型:

     

System.Xml.XmlWriter

的XmlWriter对象      

包裹指定的XmlWriter对象。

所以我假设它使用相同的对象。

编辑这是您可以使用的解决方案:

static void Main(string[] args)
    {
        var sb = new StringWriter();
        var sb2 = new StringWriter();

        using (var xml = XmlWriter.Create(sb, new XmlWriterSettings() { Indent = true }))
        {
            xml.WriteStartElement("root");

            using (var inner = XmlWriter.Create(sb2, new XmlWriterSettings() {Indent = true , CloseOutput=true, OmitXmlDeclaration=true}))
            {

                inner.WriteStartElement("payload1");
                inner.WriteStartElement("third-party-stuff");
            }

            xml.WriteRaw(sb2.ToString());

            xml.WriteStartElement("payload2");
        }

        Debug.WriteLine(sb.ToString());            
    }