我正在尝试解决与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来关闭外部的。
答案 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());
}