gpt4 book ai didi

xml - XmlDictionaryReader 真的可以处理二进制 XML 吗?如果不是,那是什么?

转载 作者:数据小太阳 更新时间:2023-10-29 02:23:12 27 4
gpt4 key购买 nike

我正在尝试写一个 debugging tool允许用户以纯文本形式查看 WCF 的新二进制 XML 格式 (application/soap +msbin1)。一旦我找到 XmlDictionaryReader class 我以为我会在几分钟内完成,但它没有按预期工作。

private string DecodeBinaryXML(byte[] binaryBuffer)
{
if (binaryBuffer == null)
{
return "";
}

try
{
var doc = new XmlDocument();
using (var binaryReader = XmlDictionaryReader.CreateBinaryReader(binaryBuffer, XmlDictionaryReaderQuotas.Max))
{
doc.Load(binaryReader);
binaryReader.Close();
}

var textBuffer = new StringBuilder();
var settings = new XmlWriterSettings()
{
// lots of code not relevant to the question
};
using (var writer = XmlWriter.Create(textBuffer, settings))
{
doc.Save(writer);
writer.Close();
}

return textBuffer.ToString();
}
catch (Exception ex)
{
// just display errors in the text viewer
return ex.ToString();
}
}

我在网上找到的或自己生成的每个“soap+msbin1”示例都会在 doc.Load() 处抛出解析异常。

为了了解发生了什么,我创建了一个简单的测试应用程序并从另一个方向解决了这个问题。

// client
static void Main(string[] args)
{
var binding = new CustomBinding(new TextMessageEncodingBindingElement(),
new HttpTransportBindingElement());
var proxy = ChannelFactory<IService1>.CreateChannel(binding,
new EndpointAddress("http://ipv4.fiddler:25381/Service1.svc"));
Console.WriteLine(proxy.Echo("asdf"));
}

// shared interface
[ServiceContract()]
public interface IService1
{
[OperationContract]
string Echo(string input);
}

// server
public class Service1 : IService1
{
public string Echo(string input)
{
return "WCF says hi to: " + input;
}
}

运行它会启动一个 http 请求,如下所示:

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" 
xmlns:a="http://www.w3.org/2005/08/addressing">
<s:Header>
<a:Action s:mustUnderstand="1">http://tempuri.org/IService1/Echo</a:Action>
<a:MessageID>urn:uuid:21a33e81-bfab-424f-a2e5-5116101a7319</a:MessageID>
<a:ReplyTo>
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
<a:To s:mustUnderstand="1">http://ipv4.fiddler:25381/Service1.svc</a:To>
</s:Header>

<s:Body>
<Echo xmlns="http://tempuri.org/">
<input>asdf</input>
</Echo>
</s:Body>
</s:Envelope>

我以两种不同的方式将此 XML 转换为二进制文件。首先,使用 XmlDictionaryWriter:

$fs = [system.io.file]::Create("c:\temp\soap.bin")
$writer = [system.xml.xmldictionarywriter]::CreateBinaryWriter($fs)
$xml = [xml] (gc C:\temp\soap.xml)
$xml.Save($writer)
$writer.Close(); $fs.Close()

然后,使用 WCF 和相同的网络嗅探器:

    @@ -1,7 +1,7 @@
// client
static void Main(string[] args)
{
- var binding = new CustomBinding(new TextMessageEncodingBindingElement(),
+ var binding = new CustomBinding(new BinaryMessageEncodingBindingElement(),
new HttpTransportBindingElement());

方法#1 给出了 397 字节的二进制文件。方法 #2 显示了 169 个字节的非常不同的二进制垃圾。除了出现在两个输出中的一些字符串外,我没有发现两种编码有太多相似之处。难怪 XmlDictionaryReader 无法理解 WCF 服务的输出!

解码这种格式有什么 secret ,还是我完全走错了路?

最佳答案

从 Carlos Figueira @ MS 那里得到了有希望的回应。

WCF uses a "static dictionary" which encode some well-known strings into (small) ids. For example, the strings "Envelope", "http://www.w3.org/2003/05/soap-envelope", "http://www.w3.org/2005/08/addressing" and so on are represented only as a few bytes. So to be able to parse the requests that are sent by WCF, you need to pass that dictionary (IXmlDictionary) to the XmlDictionaryReader.CreateBinaryReader method.

The whole dictionary is documented at http://msdn.microsoft.com/en-us/library/cc219175(PROT.10).aspx. The code to read the request should look something like:

public class Post_e9208540_7877_4318_909d_92eb8490ab58
{
static XmlDictionary dictionary;
static XmlDictionary GetDictionary()
{
if (dictionary == null)
{
XmlDictionary temp = new XmlDictionary();
dictionary = temp;
temp.Add("mustUnderstand");
temp.Add("Envelope");
temp.Add("http://www.w3.org/2003/05/soap-envelope");
temp.Add("http://www.w3.org/2005/08/addressing");
...
}
return dictionary;
}
public static void DecodeBinaryMessage(byte[] message)
{
XmlDictionaryReader reader = XmlDictionaryReader.CreateBinaryReader(message, 0, message.Length, GetDictionary(), XmlDictionaryReaderQuotas.Max);
Console.WriteLine(reader.ReadOuterXml());
}
}

如果找到有效的解决方案,我会用更多细节更新这个答案。

编辑:是的,很有魅力! Carlos 解决方案的唯一问题是 ReadOuterXml() 似乎不起作用。读入 XmlDocument 然后写出 Stream 可以更好地控制格式,所以这就是我坚持的做法。

注意:复制 MS 规范中的字典需要大约 500 行代码。我建议复制我的,除非你是受虐狂 - http://tfstoys.codeplex.com/sourcecontrol/changeset/view/26191?projectName=tfstoys#499486

关于xml - XmlDictionaryReader 真的可以处理二进制 XML 吗?如果不是,那是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1291871/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com