【问题标题】:Extract SOAP body from a SOAP message从 SOAP 消息中提取 SOAP 正文
【发布时间】:2012-05-04 21:23:02
【问题描述】:

我想从 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,因为起始块在字符串中不匹配。字符串中有什么?
  • 我还要检查prefix 是否被正确读取。您的 SOAP 命名空间不应该在中间有空格 - 删除这些有帮助吗?在这里使用适当的 XML 解析器也可能比子字符串匹配更好。
  • 正确的 XML 解析器是什么意思?我不跟着你?这就是我想读的 w3.org/2001/XMLSchema" xmlns:xsi="w3.org/2001/XMLSchema-instance" xmlns:soap= "schemas.xmlsoap.org/soap/envelope"> 1234
  • 我的意思是使用soapNode 来查找正文标签并提取您想要的内容,而不是使用子字符串匹配。查看您的示例,您在 XML 中有小写的 b“body”,但在代码中有大写的“body”。
  • 这就是问题所在,我现在不知道如何编写代码,你能帮帮我吗,我要疯了!

标签: c# soap xml-parsing


【解决方案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>";

以下代码完成了解包数据并仅获取&lt;ReponseData&gt; 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;
    

    --编辑--

    循环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 来提取soap 请求的正文。

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

      简单的解决方案,如果 body 有多个孩子,你只需要删除信封:

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

      如果你想同时删除 Envelope 和 body,其中 body 只包含一个孩子:

          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 被简化为 Body 的内容

      【讨论】:

        猜你喜欢
        • 2021-09-29
        • 2014-07-22
        • 2018-11-26
        • 2011-04-10
        • 1970-01-01
        • 1970-01-01
        • 2014-05-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多