进出 XPathDocument 的协议缓冲区消息
Posted
技术标签:
【中文标题】进出 XPathDocument 的协议缓冲区消息【英文标题】:protocol buffer message to and from an XPathDocument 【发布时间】:2011-06-24 12:25:22 【问题描述】:我正在尝试序列化和反序列化与 XPathDocument 之间的协议缓冲区消息,但它失败并出现异常: ProtoBuf.ProtoException:在消息中检测到不匹配的组标签 我该如何完成这项工作?
我正在使用 protobuf-net,我的源代码重现它看起来像这样:
TestMsg.proto
option optimize_for = SPEED;
//*************************
message Test
repeated A a = 1;
message A
required string str = 1;
程序.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.XPath;
using ProtoBuf;
using TestMsg;
namespace protocolbufferserialize
class Program
static void Main(string[] args)
Test t = new Test();
XPathDocument xmldoc = Serialize(t);
Test t1 = Serialize(xmldoc);
public static XPathDocument Serialize(Test wro)
XPathDocument xmlDoc = null;
Serializer.PrepareSerializer<Test>();
XmlSerializer x = new XmlSerializer(wro.GetType());
using (MemoryStream memoryStream = new MemoryStream())
using (TextWriter w = new StreamWriter(memoryStream))
x.Serialize(w, wro);
memoryStream.Position = 0;
xmlDoc = new XPathDocument(memoryStream);
return xmlDoc;
public static Test Serialize(XPathDocument xmlDoc)
Test t = null;
Serializer.PrepareSerializer<Test>();
XmlSerializer x = new XmlSerializer(xmlDoc.GetType());
using (MemoryStream memoryStream = new MemoryStream())
using (TextWriter w = new StreamWriter(memoryStream))
x.Serialize(w, xmlDoc);
memoryStream.Position = 0;
t = Serializer.Deserialize<Test>(memoryStream);
return t;
我试图扩展使用Serializer.Merge,但是当它从xml返回时Test对象是空的。
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.XPath;
using ProtoBuf;
using TestMsg;
namespace TestXMLSerilizationLars
class Program
static void Main(string[] args)
Test t = new Test();
A a = new A();
string str = "test";
a.str = str;
t.a.Add(a);
XPathDocument xmldoc = Serialize(t);
WriteXpathDocument(xmldoc, "c:\\testmsg.xml");
Test t1 = Serialize(xmldoc);
public static XPathDocument Serialize(Test t)
XPathDocument xmlDoc = null;
Serializer.PrepareSerializer<Test>();
XmlSerializer x = new XmlSerializer(t.GetType());
using (MemoryStream memoryStream = new MemoryStream())
using (TextWriter w = new StreamWriter(memoryStream))
x.Serialize(w, t);
memoryStream.Position = 0;
xmlDoc = new XPathDocument(memoryStream);
return xmlDoc;
public static Test Serialize(XPathDocument xmlDoc)
Test t = null;
Type type = xmlDoc.GetType();
XmlSerializer serializer = new XmlSerializer(type);
using (MemoryStream memoryStream = new MemoryStream())
serializer.Serialize(memoryStream, xmlDoc);
// memoryStream.Close();
Test newt = Deserialize(memoryStream.ToArray());
return newt;
return t;
static public Test Deserialize(byte[] Bytes)
MemoryStream SerializeStream = new MemoryStream(Bytes);
Test NewObject = Serializer.Deserialize<Test>(SerializeStream);
Test ObjectExist = new Test();
if (ObjectExist == null)
return NewObject;
else
SerializeStream.Seek(0, SeekOrigin.Begin);
Serializer.Merge<Test>(SerializeStream, ObjectExist);
return ObjectExist;
public static void WriteXpathDocument(XPathDocument xpathDoc, string filename)
// Create XpathNaviagtor instances from XpathDoc instance.
XPathNavigator objXPathNav = xpathDoc.CreateNavigator();
// Create XmlWriter settings instance.
XmlWriterSettings objXmlWriterSettings = new XmlWriterSettings();
objXmlWriterSettings.Indent = true;
// Create disposable XmlWriter and write XML to file.
using (XmlWriter objXmlWriter = XmlWriter.Create(filename, objXmlWriterSettings))
objXPathNav.WriteSubtree(objXmlWriter);
objXmlWriter.Close();
我转出的xml文件是这样的
<?xml version="1.0" encoding="utf-8"?>
<Test xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<a>
<A>
<str>test</str>
</A>
</a>
</Test>
【问题讨论】:
【参考方案1】:你在这里使用 protobuf 的唯一一次是:
x.Serialize(w, xmlDoc);
memoryStream.Position = 0;
t = Serializer.Deserialize<Test>(memoryStream);
您在哪里写入了 xml(x
是 XmlSerializer
),然后尝试通过 protobuf (Serializer.Deserialize
) 读取它。
但是; protobuf 不是 xml;它是一种与 xml 无关的二进制格式完全。如果您打算深度克隆数据,您还应该使用 protobuf-net (Serializer.Serialize
)序列化。
通常可以在两种格式之间转换一个模型,但是流本身是不可交换的。
【讨论】:
以上是关于进出 XPathDocument 的协议缓冲区消息的主要内容,如果未能解决你的问题,请参考以下文章