Хорошо, я знаю, что этот вопрос задавался давно, но я только что столкнулся с той же проблемой, поэтому я решил опубликовать свои выводы здесь.
Поскольку пространства имен xsi и xsd находятся в элементе Body, метод message.GetReaderAtBodyContents () не будет возвращать действительный xml. Я нашел два способа справиться с этим.
Сначала вы можете заключить вызов в свой собственный элемент, содержащий пространства имен xsi и xsd, а затем извлечь из него внутренний xml. Это приводит к тому, что пространства имен уточняются при использовании.
XmlReader bodyReader = message.GetReaderAtBodyContents();
// Next we wrap the possibly invalid body contents (because of missing namespaces) into our own wrapper with the namespaces specified
XmlDocument bodyDoc = new XmlDocument();
MemoryStream bodyMS = new MemoryStream();
XmlWriter w = XmlWriter.Create(bodyMS, new XmlWriterSettings {Indent = true, IndentChars = " ", OmitXmlDeclaration = true});
w.WriteStartElement("body");
w.WriteAttributeString("xmlns", "xsi", null, "http://www.w3.org/2001/XMLSchema-instance");
w.WriteAttributeString("xmlns", "xsd", null, "http://www.w3.org/2001/XMLSchema");
while (xdr.NodeType != XmlNodeType.EndElement && xdr.LocalName != "Body" && xdr.NamespaceURI != "http://schemas.xmlsoap.org/soap/envelope/")
{
if (xdr.NodeType != XmlNodeType.Whitespace)
{
w.WriteNode(xdr, true);
}
else
{
xdr.Read();
}
}
w.WriteEndElement();
w.Flush();
bodyMS.Position = 0;
bodyDoc.Load(bodyMS);
XmlNode bodyNode = bodyDoc.SelectSingleNode("body");
string innerBody = bodyNode.InnerXml;
Если вы осмотрите innerBody, вы увидите, что пространства имен xsi и xsd были квалифицированы на каждом узле, который их использует, поэтому вы можете загрузить innerBody в считыватель для проверки.
Во-вторых, вы можете просто прочитать все сообщение в xml и извлечь содержимое тела, как указано выше. Это будет иметь тот же эффект, что и выше, но будет обрабатывать любые пространства имен в элементе Body.
StringBuilder sb = new StringBuilder();
using (System.Xml.XmlWriter xw = System.Xml.XmlWriter.Create(sb))
{
message.WriteMessage(xw);
}
string theWholeMessage = sb.ToString();
XmlDocument wholeBodyDoc = new XmlDocument();
wholeBodyDoc.LoadXml(theWholeMessage);
XmlNamespaceManager wholeNS = new XmlNamespaceManager(new NameTable());
wholeNS.AddNamespace("s", "http://www.w3.org/2003/05/soap-envelope");
XmlNode wholeBodyNode = wholeBodyDoc.SelectSingleNode("//s:Body", wholeNS);
string innerBody = wholeBodyNode.InnerXml;
Здесь я просто загрузил все сообщение в построитель строк, а затем загрузил его в XmlDocument, чтобы я мог извлечь внутренний xml элемента Body. Полученный xml будет квалифицирован так же, как и в первом подходе.