【问题标题】:How to work with an XmlWriter inside another?如何在另一个内部使用 XmlWriter?
【发布时间】:2013-04-05 13:49:47
【问题描述】:

我正在尝试解决与我在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>

但是我在应该写 &lt;payload2&gt; 的行上得到一个运行时错误

无效操作异常
Writer 已关闭或处于错误状态。

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

【问题讨论】:

  • 你确定它没有在你的 ThirdPartyLibrary.Serialise(results, inner); 中被关闭吗?方法调用?
  • @Penfold 好点。更改了我上面的示例,以便您可以运行它。

标签: c# .net xml xmlwriter


【解决方案1】:

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

这样的代码会产生代码分析错误CA2202。以下link 描述了对此类情况的解决方案。

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-06
      • 2019-05-30
      相关资源
      最近更新 更多