Извлечь тело SOAP из сообщения SOAP

Я хочу извлечь тело SOAP из сообщения SOAP, у меня есть некоторые данные в теле SOAP, которые я должен проанализировать в базе данных, поэтому это код:

public string Load_XML(string SoapMessage)
{
    //check soap message
    if (SoapMessage == null || SoapMessage.Length <= 0)
        throw new Exception("Soap message not valid");

    //declare some local variable
    int iSoapBodyStartIndex = 0;
    int iSoapBodyEndIndex = 0;

    //load the Soap Message
    //Učitaj string XML-a i pretvori ga u XML
    XmlDocument doc = new XmlDocument();

    try
    {
        doc.Load(SoapMessage);
    }

    catch (XmlException ex)
    {
        WriteErrors.WriteToLogFile("WS.LOAD_DOK_LoadXML", ex.ToString());

        throw ex;
    }

    //search for the "http://schemas.xmlsoap.org/soap/envelope/" URI prefix
    string prefix = string.Empty;
    for (int i = 0; i < doc.ChildNodes.Count; i++)
    {
        System.Xml.XmlNode soapNode = doc.ChildNodes[i];
        prefix = soapNode.GetPrefixOfNamespace("http://schemas.xmlsoap.org  /soap/envelope/");

        if (prefix != null && prefix.Length > 0)
            break;
    }

    //prefix not founded. 
    if (prefix == null || prefix.Length <= 0)
        throw new Exception("Can't found the soap envelope prefix");

    //find soap body start index
    int iSoapBodyElementStartFrom = SoapMessage.IndexOf("<" + prefix + ":Body");
    int iSoapBodyElementStartEnd = SoapMessage.IndexOf(">", iSoapBodyElementStartFrom);    -> HERE I HAVE AN ERROR!!!!   
    iSoapBodyStartIndex = iSoapBodyElementStartEnd + 1;

    //find soap body end index
    iSoapBodyEndIndex = SoapMessage.IndexOf("</" + prefix + ":Body>") - 1;

    //get soap body (xml data)
    return SoapMessage.Substring(iSoapBodyStartIndex, iSoapBodyEndIndex - iSoapBodyStartIndex + 1);
}

Я получил ошибку здесь:

int iSoapBodyElementStartEnd = SoapMessage.IndexOf(">", iSoapBodyElementStartFrom); 

Ошибка:

Индекс оказался вне допустимого диапазона. Должен быть неотрицательным и меньше, чем размер коллекции.

Если кто-нибудь знает, как это решить?

Ответ 1

Для запроса, подобного этому:

String request = @"<?xml version=""1.0"" encoding=""UTF-8""?>
    <soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance""
    xmlns:soapenc=""http://schemas.xmlsoap.org/soap/encoding/""
    xmlns:xsd=""http://www.w3.org/2001/XMLSchema""
    xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
    <soap:Body>
    <ResponseData xmlns=""urn:Custom"">some data</ResponseData>
    </soap:Body>
    </soap:Envelope>";

Следующий код выполнил работу по распаку данных и получил только содержимое <ReponseData> xml:

XDocument xDoc = XDocument.Load(new StringReader(request));

var unwrappedResponse = xDoc.Descendants((XNamespace)"http://schemas.xmlsoap.org/soap/envelope/" + "Body")
    .First()
    .FirstNode

Ответ 2

Linq2Xml проще использовать.

string xml = @"<?xml version=""1.0"" encoding=""UTF-8"" ?>
    <soap:envelope xmlns:xsd=""w3.org/2001/XMLSchema"" xmlns:xsi=""w3.org/2001/XMLSchema-instance"" xmlns:soap=""schemas.xmlsoap.org/soap/envelope/"">; 
    <soap:body> 
    <order> <id>1234</id>  </order> 
    </soap:body> 
    </soap:envelope>";

XDocument xDoc = XDocument.Load(new StringReader(xml));
var id =  xDoc.Descendants("id").First().Value;

- EDIT -

Чтобы зацикливать элементы в body:

XDocument xDoc = XDocument.Load(new StringReader(xml));
XNamespace soap = XNamespace.Get("schemas.xmlsoap.org/soap/envelope/");

var items = xDoc.Descendants(soap+"body").Elements();
foreach (var item in items)
{
    Console.WriteLine(item.Name.LocalName);
}

Ответ 3

Вы можете использовать GetElementsByTagName для извлечения тела запроса на мыло.

private static T DeserializeInnerSoapObject<T>(string soapResponse)
{
    XmlDocument xmlDocument = new XmlDocument();
    xmlDocument.LoadXml(soapResponse);

    var soapBody = xmlDocument.GetElementsByTagName("soap:Body")[0];
    string innerObject = soapBody.InnerXml;

    XmlSerializer deserializer = new XmlSerializer(typeof(T));

    using (StringReader reader = new StringReader(innerObject))
    {
        return (T)deserializer.Deserialize(reader);
    }
}

Ответ 4

Простое решение, если в теле несколько детей, и вам нужно просто удалить конверт:

    XmlDocument xmlDoc = new XmlDocument();
    xmlDoc.LoadXml(placeYourXmlHere);

    if (xmlDoc.DocumentElement.Name == "soapenv_Envelope")
    {
        string tempXmlString = xmlDoc.DocumentElement.InnerXml;
        xmlDoc.LoadXml(tempXmlString);
    }

Если вы хотите удалить и конверт, и тело, где тело содержит только одного ребенка:

    XmlDocument xmlDoc = new XmlDocument();
    xmlDoc.LoadXml(placeYourXmlHere);

    while (xmlDoc.DocumentElement.Name == "soapenv_Envelope" || xmlDoc.DocumentElement.Name == "soapenv_Body")
    {
        string tempXmlString = xmlDoc.DocumentElement.InnerXml;
        xmlDoc.LoadXml(tempXmlString);
    }

Теперь XML сводится к содержанию тела