2012-04-24 24 views
11

chcę wydobyć ciało SOAP z wiadomości SOAP, mam pewne dane w organizmie SOAP, że muszę analizować w dniu bazowym, więc jest to kod:Extract ciało SOAP z komunikatem 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); 
} 

mam błąd tutaj:

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

błąd:

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

Jeśli ktoś wie jak rozwiązać ten problem?

+0

Czy to zdecydowanie nieujemne? Domyślam się, że jest -1, ponieważ blok początkowy nie był dopasowany w ciągu znaków. Co zawiera ciąg? – Rup

+0

Sprawdziłbym również, czy 'przedrostek' jest poprawnie odczytany. Twoja przestrzeń nazw SOAP nie powinna zawierać spacji w środku - czy usuwa tę pomoc? Lepszym rozwiązaniem może być tutaj użycie odpowiedniego parsera XML zamiast dopasowywania podłańcuchów. – Rup

+0

Co masz na myśli przez odpowiedni parser XML? Nie podążam za tobą? To właśnie chcę przeczytać CrBruno

Odpowiedz

10

Do wniosku jak ten:

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

Poniższy kod nie pracy aby odwijać dane i uzyskać tylko plik XML o wartości <ReponseData> treść:

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

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

Linq2Xml jest prostszy w użyciu.

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

Do elementów pętlowych w 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 dzięki, tylko jedno małe pytanie, czy chcę wyodrębnić wszystkie elementy w segmencie ciała, a nie tylko pierwsze i ostatnie, jak je napisać? – CrBruno

+1

@Bruno Edytowałem odpowiedź. –

1

Możesz użyć GetElementsByTagName, aby wyodrębnić treść żądania mydła.

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