如何正确处理这个 XML 响应 (SOAP:Envelope)?

How to handle this XML response (SOAP:Envelope) correctly?

我向我们公司的 HP 服务经理创建了一个 Web 请求,以收集一些数据。 结果是:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
   <SOAP-ENV:Body>
      <RetrieveSuegChangeListResponse message="Success" returnCode="0" schemaRevisionDate="2015-04-22" schemaRevisionLevel="0" status="SUCCESS" xsi:schemaLocation="http://schemas.hp.com/SM/7 http://servicemanager-ws.intranet.example.com:12345/SM/7/SuegChange.xsd" xmlns="http://schemas.hp.com/SM/7" xmlns:cmn="http://schemas.hp.com/SM/7/Common" xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
         <instance query="" recordid="CM00088641 - Server: Migration of the SSH-HOP" uniquequery="header,number=&quot;CM00088641&quot;">
            <header type="Structure">
               <Number type="String">CM00088641</Number>
               <PlannedStart type="DateTime">2015-07-06T06:00:00+00:00</PlannedStart>
               <PlannedEnd type="DateTime">2015-07-06T18:00:00+00:00</PlannedEnd>
               <Title type="String">Server: Migration of the SSH-HOP</Title>
            </header>
            <middle type="Structure">
               <AffectedCi type="Array">
                  <AffectedCi type="String">SERVER1</AffectedCi>
                  <AffectedCi type="String">SERVER2</AffectedCi>
                  <AffectedCi type="String">SERVER3</AffectedCi>
               </AffectedCi>
            </middle>
         </instance>
      </RetrieveSuegChangeListResponse>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

现在我正尝试从此结果中获取信息,但我在使用以下 C# 代码时遇到了麻烦:

public static string gettextfromWebserviceChange()
        {
            #region suchen im XML
            XmlDocument  objReturn = new XmlDocument();
            string result = @"<SOAP-ENV:Envelope xmlns:SOAP-ENV=""http://schemas.xmlsoap.org/soap/envelope/"">
                                       <SOAP-ENV:Body>
                                          <RetrieveSuegChangeListResponse message=""Success"" returnCode=""0"" schemaRevisionDate=""2015-04-22"" schemaRevisionLevel=""0"" status=""SUCCESS"" xsi:schemaLocation=""http://schemas.hp.com/SM/7 http://servicemanager-ws.intranet.example.com:12345/SM/7/SuegChange.xsd"" xmlns=""http://schemas.hp.com/SM/7"" xmlns:cmn=""http://schemas.hp.com/SM/7/Common"" xmlns:xmime=""http://www.w3.org/2005/05/xmlmime"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"">
                                             <instance query="" recordid=""CM00088641 - Server: Migration of the SSH-HOP"" uniquequery=""header,number=&quot;CM00088641&quot;"">
                                                <header type=""Structure"">
                                                   <Number type=""String"">CM00088641</Number>
                                                   <PlannedStart type=""DateTime"">2015-07-06T06:00:00+00:00</PlannedStart>
                                                   <PlannedEnd type=""DateTime"">2015-07-06T18:00:00+00:00</PlannedEnd>
                                                   <Title type=""String"">Server: Migration of the SSH-HOP</Title>
                                                </header>
                                                <middle type=""Structure"">
                                                   <AffectedCi type=""Array"">
                                                      <AffectedCi type=""String"">SERVER1</AffectedCi>
                                                      <AffectedCi type=""String"">SERVER2</AffectedCi>
                                                      <AffectedCi type=""String"">SERVER3</AffectedCi>
                                                   </AffectedCi>
                                                </middle>
                                             </instance>
                                          </RetrieveSuegChangeListResponse>
                                       </SOAP-ENV:Body>
                                    </SOAP-ENV:Envelope>";
                    objReturn.LoadXml(result);
                    
                    List<String> ListAffectedCi = new List<string>();
                    String Descriptiontxt = "";
                    String ChangeStartDate = "";
                    String ChangeEndDate = "";
                    StringBuilder builder = new StringBuilder();


                    //ToDo: which is the right NameSpace!!!!!!!!!
                    XmlNamespaceManager namespaces = new XmlNamespaceManager(objReturn.NameTable);
                    namespaces.AddNamespace("SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/");
                    //XmlNode idNode = doc.SelectSingleNode("/My_RootNode/ns:id", namespaces);

                    XmlNodeList xnList = objReturn.GetElementsByTagName("header");
                    foreach (XmlNode xn in xnList)
                    {
                        ChangeStartDate = xn["PlannedStart"].InnerText;
                        ChangeEndDate = xn["PlannedEnd"].InnerText;
                        Descriptiontxt = xn["Title"].InnerText.Trim();
                    }

                    XmlNodeList xnList2 = objReturn.GetElementsByTagName("AffectedCi");
                    int i = 1;// xnList2.Count;
                    foreach (XmlNode xn in xnList2)
                    {
                            // here i'm get in trouble...
                            ListAffectedCi.Add(xn["AffectedCi"].InnerText);

                        
                    }


            #endregion
            #region zusammenbau des strings
                        /////////////////

                        // Append a string to the StringBuilder and then another line break.
                        builder.Append("<b>Title :</b> " + Descriptiontxt + "<br />");
                        builder.Append("<b>Resource :</b> " + String.Join(", ", ListAffectedCi) + "<br />");
                        DateTime _ChangeStartDate = DateTime.Parse(ChangeStartDate, null, System.Globalization.DateTimeStyles.RoundtripKind);
                        DateTime _ChangeEndDate = DateTime.Parse(ChangeEndDate, null, System.Globalization.DateTimeStyles.RoundtripKind);
                        TimeSpan span = _ChangeEndDate.Subtract ( _ChangeStartDate );

                        //"yyyy-MM-ddTHH:mm:ss.fff"
                        builder.Append("<b>Dauer :</b> " + _ChangeStartDate.ToString("dd.MM.yyyy HH:mm:ss") + "    -    " + " " + _ChangeEndDate.ToString("dd.MM.yyyy HH:mm:ss") + "<br />");
                        builder.Append("<b>Zeitspanne :</b> " + span.Days + " Tage und " + span.Hours + " Stunden.<br />");
                        //builder.Append("<dl><dt><b>Zeitspanne :</b></dt><dd>" + span.Days + " Tage</dd><dd>" + span.Hours + " Stunden</dd><dd>" + span.Minutes + " Minuten</dd><dd>" + span.Seconds + " Sekunden</dd><dd>" + span.Ticks + " Ticks</dd></dl>");

#endregion

            return builder.ToString();
        }

我的问题是,我收到一个包含 4 个 AffectedCI 的列表...3 个已填充,一个为空,这会创建一个未处理的 NullReferenceException。 有谁知道如何处理好这个 XML?

我也尝试过使用 Xpath...但是我很愚蠢地为那个找到正确的命名空间 XML...否则我可以直接转到 AffectedCI 路径以获得正确数量的CI...

希望有人能帮助我! 先感谢您, 最好的问候

如果您不喜欢 XmlDocument,LINQ to XML 是一个更好的解决方案:

XNamespace ns = "http://schemas.hp.com/SM/7";

var doc = XDocument.Parse(result);

var header = doc.Descendants(ns + "header").Single();

var start = (DateTime)header.Element(ns + "PlannedStart");
var end = (DateTime)header.Element(ns + "PlannedEnd");
var description = (string)header.Element(ns + "Title");

var affectedCis = doc.Descendants(ns + "AffectedCi")
    .Where(e => (string)e.Attribute("type") == "String")
    .Select(e => e.Value)
    .ToList();