2012-04-24 13 views
11

Quiero extraer cuerpo SOAP de un mensaje SOAP, tengo algunos datos en cuerpo SOAP que tengo que analizar en la base de la fecha, por lo que este es el código:Extracto de cuerpo SOAP de un mensaje 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); 
} 

tengo un error aquí:

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

El error:

Index was out of range. Must be non-negative and less than the size of the collection.

Si alguien sabe cómo solucionar esto?

+0

¿Es definitivamente no negativo? Supongo que es -1 porque el bloque de inicio no coincidía en la cadena. ¿Qué hay en la cadena? – Rup

+0

También verificaría si 'prefix' se lee correctamente. Su espacio de nombres SOAP no debe tener espacios en el medio - ¿elimina esa ayuda? También puede ser mejor utilizar un analizador XML adecuado aquí en lugar de la coincidencia de subcadenas. – Rup

+0

¿Qué quiere decir con un analizador XML correcto? No te estoy siguiendo? Esto es lo que quiero leer CrBruno

Respuesta

10

Para una solicitud como esta:

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>"; 

El código siguiente hizo el trabajo para desenvolver los datos y obtener solo el <ReponseData> xml contenido:

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

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

Linq2Xml es más fácil de usar.

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--

Para elementos de bucle en 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); 
} 
+0

O gracias, solo una pequeña pregunta, si quiero extraer todos los elementos en el segmento del cuerpo, no solo el primero y el último, ¿cómo escribirlo? – CrBruno

+1

@Bruno Edité la respuesta. –

1

Usted puede utilizar GetElementsByTagName para extraer el cuerpo de la petición de jabón.

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); 
    } 
}