单流、多个 XmlWriter

发布于 2024-08-19 12:50:31 字数 436 浏览 8 评论 0原文

是否可以有一个流并让多个 XmlWriter 写入该流并最终得到格式良好的 XML?

我有一个对象层次结构,其中每个对象单独且完全负责序列化自身。我最近的尝试是在最高级别创建一个流,然后将该流引用向下传递并允许每个对象创建自己的 XmlWriter 以将其自身序列化到流中。然而,这最终会在不完整的父节点中创建节点(在写入子内容之前,即使使用刷新,起始元素也没有在父节点中完全形成)。

有多个应用程序域,因此传递 XmlWriter 引用将不起作用。我让每个对象返回一个字符串并将原始 XML 字符串写入流中,但有些字符串变得非常非常长(集合)。这就是我决定使用流的原因——这样每个对象都可以一次写出一小部分,并且流实例既可序列化又具有 MBR。

由于我似乎没有记录的原因,我决定不使用 XmlSerializer。但我会相信我之前的判断。

感谢任何可以让我更彻底地了解我正在从事的工作的事情。

Is it possible to have a single stream and have more than one XmlWriter write to that stream and end up with well-formed XML?

I have an object hierarchy in which each object is solely and fully responsible for serializing itself. My latest attempt has been to create a stream at the highest level, then pass that stream reference down and allow each object to create its own XmlWriter to serialize itself to the stream. However, this ends up creating nodes within incomplete parent nodes (the start element is not fully formed in the parent before child content is written, even with a flush).

There are multiple appdomains, so passing the XmlWriter reference will not work. I was having each object return a string and writing that raw XML string into the stream, but some of the strings get to be very, very long (collections). That's why I decided on a stream -- so that each object could write out small pieces at a time and a stream instance is both serializable and MBR.

I decided against using XmlSerializer for reasons I didn't seem to document. But I'm going to trust my earlier judgment on that.

Thanks for anything that can lead to a more thorough understanding of what I'm working with.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

痴情换悲伤 2024-08-26 12:50:31

您可能只想将每个类的 xml 部分作为字符串写入流,而不是使用 XmlWriter。这使您可以完全控制结束标签。但我已经创建了一个似乎有效的解决方法。这允许您在应用程序域之间传递可序列化的流。

首先使用一个辅助类来初始化新的 XmlWriters 并在传递它之前修复流。

public static class XmlWriterExt
{
    /// <summary>
    /// Make sure any previous tag is ended by writing dummy text, then backtracking the position
    /// </summary>
    public static void PrepareStream(this XmlWriter writer, Stream stream)
    {
        writer.WriteElementString("x", string.Empty);
        writer.Flush();
        stream.Position -= 5; //backtrack the dummy element
    }

    /// <summary>
    /// Get an xml writer which works on fragments and without the xml declaration
    /// </summary>
    public static XmlWriter GetWriter(Stream stream)
    {
        XmlWriterSettings settings = new XmlWriterSettings();
        settings.OmitXmlDeclaration = true;
        settings.ConformanceLevel = ConformanceLevel.Fragment;
        XmlWriter xmlWriter = XmlWriter.Create(stream, settings);
        return xmlWriter;
    }
}

这是几个相互嵌套的测试类。

class TopClass
{
    InnerClass _innerClass = new InnerClass();

    public void Serialize(Stream stream)
    {
        XmlWriter xmlWriter = XmlWriterExt.GetWriter(stream);
        xmlWriter.WriteStartElement("top");
        xmlWriter.PrepareStream(stream);
        _innerClass.Serialize(stream);
        xmlWriter.WriteEndElement();
        xmlWriter.Flush();
    }
}

class InnerClass
{
    public void Serialize(Stream stream)
    {
        XmlWriter xmlWriter = XmlWriterExt.GetWriter(stream);
        xmlWriter.WriteElementString("b", "testing");
        xmlWriter.Flush();
    }
}

测试代码

MemoryStream ms = new MemoryStream();
TopClass top = new TopClass();
top.Serialize(ms);

string result = Encoding.UTF8.GetString(ms.ToArray());

及结果

<top>
  <b>testing</b>
</top>

You might want to just write the xml parts per class as strings to the stream instead of using the XmlWriter. This allows you full control over ending tags. But I've created a workaround which seems to work. This allows you to pass the stream which is serializable between appdomains.

First off a helper class to initialize new XmlWriters and fixing the stream before we pass it on.

public static class XmlWriterExt
{
    /// <summary>
    /// Make sure any previous tag is ended by writing dummy text, then backtracking the position
    /// </summary>
    public static void PrepareStream(this XmlWriter writer, Stream stream)
    {
        writer.WriteElementString("x", string.Empty);
        writer.Flush();
        stream.Position -= 5; //backtrack the dummy element
    }

    /// <summary>
    /// Get an xml writer which works on fragments and without the xml declaration
    /// </summary>
    public static XmlWriter GetWriter(Stream stream)
    {
        XmlWriterSettings settings = new XmlWriterSettings();
        settings.OmitXmlDeclaration = true;
        settings.ConformanceLevel = ConformanceLevel.Fragment;
        XmlWriter xmlWriter = XmlWriter.Create(stream, settings);
        return xmlWriter;
    }
}

Here's a couple of test classes, nested in each other.

class TopClass
{
    InnerClass _innerClass = new InnerClass();

    public void Serialize(Stream stream)
    {
        XmlWriter xmlWriter = XmlWriterExt.GetWriter(stream);
        xmlWriter.WriteStartElement("top");
        xmlWriter.PrepareStream(stream);
        _innerClass.Serialize(stream);
        xmlWriter.WriteEndElement();
        xmlWriter.Flush();
    }
}

class InnerClass
{
    public void Serialize(Stream stream)
    {
        XmlWriter xmlWriter = XmlWriterExt.GetWriter(stream);
        xmlWriter.WriteElementString("b", "testing");
        xmlWriter.Flush();
    }
}

Test code

MemoryStream ms = new MemoryStream();
TopClass top = new TopClass();
top.Serialize(ms);

string result = Encoding.UTF8.GetString(ms.ToArray());

and result

<top>
  <b>testing</b>
</top>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文