AdvancedDNA Ответов: 3

Возврат данных узла XML с помощью C#


У меня есть следующие XML-результаты, которые генерируются при запуске SOAP-запроса к веб-сервису.

 <?xml version="1.0" encoding="utf-8" ?> 
- <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
- <SOAP-ENV:Body>
- <idc:service xmlns:idc="http://www.stellent.com/IdcService/" IdcService="SEARCH_WORKFLOWS">
- <idc:document dUser="user">
  <idc:field name="SearchAuthor" /> 
  <idc:field name="SearchCID">arf</idc:field> 
  <idc:field name="SearchAssn" /> 
- <idc:resultset name="WfDocuments">
- <idc:row dDocName="ARF16-0711" dID="596213" dDocType="JPS_QMARF" dDocTitle="ARF16-0711 AMYWSA3377 Prop Lbl Prod PV Mat LStatn" dDocAuthor="author" dRevClassID="283640" dRevisionID="1" dRevLabel="A0" dIsCheckedOut="0" dCheckoutUser="" dSecurityGroup="Submitted_Forms" dCreateDate="8/23/16 3:10 PM" dInDate="8/23/16 3:10 PM" dOutDate="" dStatus="REVIEW" dReleaseState="E" dFlag1="" dWebExtension="hcsp" dProcessingState="Y" dMessage="" dDocAccount="" dReleaseDate="" dRendition1="" dRendition2="" dIndexerState="" dPublishType="" dPublishState="">
</idc:row>
  </idc:resultset>
  </idc:document>
  </idc:service>
  </SOAP-ENV:Body>
  </SOAP-ENV:Envelope>


Полная строка вызова SOAP https://auhjpsv01/stellent/idcplg?=SEARCH_WORKFLOWS&амп IdcService;SearchAssn=&ампер;SearchCID=АРФ&амп;SearchAuthor=&ампер;IsSoap=1[^]

Я хочу разобрать данные узла dDocName (ARF16-0711) и данные узла dCreateDate (8/23/16 3:10 вечера) в текстовое поле, но продолжаю получать следующую ошибку с моим кодом.

<soap-env:envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:body>
<soap-env:fault>
<faultcode>Client</faultcode>
<faultstring>The Soap request is invalid.  The service node '(null)' is invalid.</faultstring>
</soap-env:fault>
</soap-env:body>
</soap-env:envelope>


Что я уже пробовал:

Вот мой код.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;

namespace SOAP_reference
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            setupWebServiceSOAPCall();            
        }

        public void setupWebServiceSOAPCall()
        {
            var _url = "https://auhjpsv01/stellent/idcplg?IdcService=SEARCH_WORKFLOWS&SearchAssn=&SearchCID=arf&SearchAuthor=&IsSoap=1";
            var _action = "https://auhjpsv01/stellent/idcplg?IdcService=SEARCH_WORKFLOWS&SearchAssn=&SearchCID=arf&SearchAuthor=&IsSoap=1";

            XmlDocument soapEnvelopeXml = CreateSOAPXMLEnvelope();
            HttpWebRequest webRequest = CreateSOAPWebRequest(_url, _action);
            InsertSoapEnvelopeIntoWebRequest(soapEnvelopeXml, webRequest);

            // begin async call to web request.
            IAsyncResult asyncResult = webRequest.BeginGetResponse(null, null);

            // suspend this thread until call is complete. You might want to
            // do something usefull here like update your UI.
            asyncResult.AsyncWaitHandle.WaitOne();

            // get the response from the completed web request.
            string soapResult;
            using (WebResponse webResponse = webRequest.EndGetResponse(asyncResult))
            {
                using (StreamReader rd = new StreamReader(webResponse.GetResponseStream()))
                {
                    soapResult = rd.ReadToEnd();
                }
                Console.Write(soapResult);
                textBox1.Text = soapResult;
            } 
        }

        private static HttpWebRequest CreateSOAPWebRequest(string url, string action)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Headers.Add("SOAPAction", action);
            request.ContentType = "text/xml;charset=\"utf-8\"";
            request.Accept = "text/xml";
            request.Method = "POST";
            return request;
        }

        private static XmlDocument CreateSOAPXMLEnvelope()
        {
            XmlDocument envelop = new XmlDocument();
            envelop.LoadXml(@"<idc:document duser="" gittlera="" xmlns:idc="#unknown"><idc:field name="" searchauthor="" /><idc:field name="" searchcid="">arf</idc:field><idc:field name="" searchassn="" /><idc:resultset name="" wfdocuments=""></idc:resultset></idc:document><soap-env:body xmlns:soap-env="#unknown"></soap-env:body>");
            return envelop;
        }

        private static void InsertSoapEnvelopeIntoWebRequest(XmlDocument soapEnvelopeXml, HttpWebRequest webRequest)
        {
            using (Stream stream = webRequest.GetRequestStream())
            {
                soapEnvelopeXml.Save(stream);
            }
        }
    }
}

3 Ответов

Рейтинг:
23

cigwork

То, как сформулирован вопрос, заставляет меня думать, что вы уже получили ответ от веб-службы, но не можете извлечь информацию. хочешь? Если так, то вот один из способов ...

Поддельный вызов веб-службы со свойством только для чтения, возвращающим данные для анализа.

/// <summary>
/// The data returned by the web service.
/// </summary>
public static string soapData {
  get {
    return @"<?xml version=""1.0"" encoding=""utf-8"" ?>
      <SOAP-ENV:Envelope xmlns:SOAP-ENV=""http://schemas.xmlsoap.org/soap/envelope/"">
        <SOAP-ENV:Body>
          <idc:service xmlns:idc=""http://www.stellent.com/IdcService/"" IdcService=""SEARCH_WORKFLOWS"">
            <idc:document dUser=""user"">
              <idc:field name=""SearchAuthor"" />
              <idc:field name=""SearchCID"">arf</idc:field>
              <idc:field name=""SearchAssn"" />
              <idc:resultset name=""WfDocuments"">
                <idc:row dDocName=""ARF16-0711"" dID=""596213""
                         dDocType=""JPS_QMARF""
                         dDocTitle=""ARF16-0711 AMYWSA3377 Prop Lbl Prod PV Mat LStatn""
                         dDocAuthor=""author""
                         dRevClassID=""283640"" dRevisionID=""1"" dRevLabel=""A0""
                         dIsCheckedOut=""0"" dCheckoutUser=""""
                         dSecurityGroup=""Submitted_Forms""
                         dCreateDate=""8/23/16 3:10 PM""
                         dInDate=""8/23/16 3:10 PM"" dOutDate=""""
                         dStatus=""REVIEW"" dReleaseState=""E"" dFlag1=""""
                         dWebExtension=""hcsp"" dProcessingState=""Y""
                         dMessage="""" dDocAccount="""" dReleaseDate=""""
                         dRendition1="""" dRendition2="""" dIndexerState=""""
                         dPublishType="""" dPublishState="""">
                </idc:row>
              </idc:resultset>
            </idc:document>
          </idc:service>
        </SOAP-ENV:Body>
      </SOAP-ENV:Envelope>";
  }
}


Теперь метод извлечения информации. нас это интересует. Это сложный код для выбора только одного типа узла (он выберет все узлы этого типа) и извлечения только атрибутов, упомянутых в вопросе.
/// <summary>
/// Hard coded to read two attributes from a single node selected by xpath.
/// </summary>
/// <param name="soapmessage"></param>
public static void read(string soapmessage) {


  XmlDocument document = new XmlDocument();
  document.LoadXml(soapmessage);  //loading soap message as string

  // Set up the namespace for the idc service.
  // Need it to allow xpath selection of prefixed nodes.
  // Just for fun comment out these lines and use
  // document.SelectNodes("//idc:row") instead of the current call to see
  // what happens.
  XmlNamespaceManager manager = new XmlNamespaceManager(document.NameTable);
  manager.AddNamespace("idc", "http://www.stellent.com/IdcService/");

  XmlNodeList xnList = document.SelectNodes("//idc:row", manager);
  int nodes = xnList.Count;

  foreach (XmlNode xn in xnList) {
    // Get the attribute values of interest.
    // Attributes is a collection.
    // Beware null exception where an attribute is optional and isn't
    // found on a node.
    Console.WriteLine("Doc: {0} Created: {1}",
                      xn.Attributes["dDocName"].Value,
                      xn.Attributes["dCreateDate"].Value);
  }


}


и проверить это...

/// <summary>
/// Test it.
/// </summary>
public static void test() {
  read(soapData);
}


Выход

Doc: ARF16-0711 Created: 8/23/16 3:10 PM


LINQ для XML-это альтернатива.


AdvancedDNA

Спасибо, сигворк. Я думаю, что это сработает, если я возьму ответ от веб-службы и получу к нему прямой доступ. Я попробую это сделать и соответственно пересмотрю свой вопрос. Чтобы уточнить, у меня возникли проблемы с написанием мыльного конверта для звонка. Возврат от этого вызова динамичен и будет меняться почти каждый час, поэтому я пытаюсь написать программу, чтобы поставить приоритет на возвращаемое имя dDocName на основе dCreateDate, чтобы определить, над каким элементом моя команда должна работать в первую очередь.

Maciej Los

5ед!

Рейтинг:
16

AdvancedDNA

Спасибо Вам за вашу работу. Еще один вопрос: XML-данные, которые извлекаются при выполнении вызова SOAP, имеют кучу полей, из одного из которых мне нужно извлечь данные.. Как мне извлечь значение из idc:field name= " dWfStepName?

Мне нужно отфильтровать список, который я возвращаю из XML-данных, на основе значения этого поля.

Я пытаюсь вытащить список активных рабочих процессов на основе того, кто должен выполнить над ними действие. Если dWfStepName = Workcell, я не хочу, чтобы ddoc-имя было в списке, иначе, если оно содержит что-то еще, я хочу заполнить список ddoc-именем и dCreateDate.

& lt;?xml version=" 1.0 "encoding=" utf-8"? >
- &ЛТ;мыло-конверты:конверт описание:мыло-Пер="http://schemas.xmlsoap.org/soap/envelope/"&ГТ;
- <мыло-ENV: Body>
- &ЛТ;IDC под услуги описание:компания IDC="http://www.stellent.com/IdcService/" IdcService= "SEARCH_WORKFLOWS" >
- <idc:document dUser= "пользователь">
< idc:имя поля= "SearchAuthor" />
&ЛТ;IDC под названием "имя поля" ="SearchCID"&ГТ;АРФ&ЛТ;/МЦД:поля&ГТ;
&ЛТ;IDC под названием "имя поля" ="SearchAssn" /&ГТ;
- <idc:resultset name= "WfDocuments">
- &ЛТ;IDC под ряд dDocName="ARF16-0711" сделал="596213" dDocType="JPS_QMARF" dDocTitle="ARF16-0711 AMYWSA3377 опоры прод ЛБЛ ПВ мат LStatn" dDocAuthor="автор" dRevClassID="283640" dRevisionID="1" dRevLabel="А0" dIsCheckedOut="0" dCheckoutUser="" dSecurityGroup="Submitted_Forms" dCreateDate="8/23/16 3:10 вечера" dInDate="8/23/16 3:10 вечера" dOutDate="" dStatus="комментарий" dReleaseState="е" dFlag1="" dWebExtension="соучредителями" dProcessingState="г" dMessage="" dDocAccount="" dReleaseDate="" dRendition1="" dRendition2="" dIndexerState="" dPublishType="" dPublishState=""&ГТ;
&ЛТ;IDC под названием "имя поля" ="dWfID">В 1741&ЛТ;/МЦД:поля&ГТ;
&ЛТ;IDC под названием "имя поля" ="dWfDocState">По ходу процесса&ЛТ;/МЦД:поля&ГТ;
< idc:имя поля= "dWfComputed" />
&ЛТ;IDC под названием "имя поля" ="dWfCurrentStepID"&ГТ;6168&ЛТ;/МЦД:поля&ГТ;
&ЛТ;IDC под названием "имя поля" ="dWfDirectory"&ГТ;submitted_forms&ЛТ;/МЦД:поля&ГТ;
&ЛТ;IDC под названием "имя поля" ="dClbraName" /&ГТ;
&ЛТ;IDC под названием "имя поля" ="dWorkflowState"&ГТ;Р&ЛТ;/МЦД:поля&ГТ;
&ЛТ;IDC под названием "имя поля" ="dRevRank"и gt;0&ЛТ;/МЦД:поля&ГТ;
&ЛТ;IDC под названием "имя поля" ="xReferenced_By" /&ГТ;
&ЛТ;IDC под названием "имя поля" ="xNew_Assembly"и GT;нет&ЛТ;/МЦД:поля&ГТ;
&ЛТ;IDC под названием "имя поля" ="xNew_Product_Containment" /&ГТ;
&ЛТ;IDC под названием "имя поля" ="xBay_Number" /&ГТ;
&ЛТ;IDC под названием "имя поля" ="xWave_Number" /&ГТ;
&ЛТ;IDC под названием "имя поля" ="xCell_Number" /&ГТ;
&ЛТ;IDC под названием "имя поля" ="xVendor" /&ГТ;
&ЛТ;IDC под названием "имя поля" ="xPlant" /&ГТ;
< idc:имя поля= "xIndustry" />
&ЛТ;IDC под названием "имя поля" ="xAffected_Departments" /&ГТ;
< idc:имя поля= "xIDCPlacement" />
&ЛТ;IDC под названием "имя поля" ="xProduct_Group" /&ГТ;
&ЛТ;IDC под названием "имя поля" ="xIDCWatermark"и GT;нет&ЛТ;/МЦД:поля&ГТ;
&ЛТ;IDC под имя поля="xCustomer"&ГТ;Амвей&ЛТ;/МЦД:поля&ГТ;
< idc:имя поля= "xIDCSecureChange" />
&ЛТ;IDC под названием "имя поля" ="xIDCSecurePrint"и GT;включить&ЛТ;/МЦД:поля&ГТ;
&ЛТ;IDC под названием "имя поля" ="xIDCSecureSelect" /&ГТ;
&ЛТ;IDC под названием "имя поля" ="xIDCSecureNotes" /&ГТ;
< idc:имя поля= "xSystem_Internal" />
&ЛТ;IDC под названием "имя поля" ="xImpacts_EMS" /&ГТ;
&ЛТ;IDC под названием "имя поля" ="xCustomer_ECO_Number" /&ГТ;
< idc:имя поля= "xDistribution" />
&ЛТ;IDC под названием "имя поля" ="xCustomer_Deviation" /&ГТ;
&ЛТ;IDC под названием "имя поля" ="xAssembly_Number"&ГТ;AMYWSA3377&ЛТ;/МЦД:поля&ГТ;
&ЛТ;IDC под названием "имя поля" ="xPart_Number" /&ГТ;
&ЛТ;IDC под названием "имя поля" ="xComments" /&ГТ;
&ЛТ;IDC под названием "имя поля" ="xReference_Documents"и GT;,&ЛТ;/МЦД:поля&ГТ;
< idc:имя поля= "xworkflowRouting" />
< idc:имя поля= "xphase" />
&ЛТ;IDC под имя поля="xAssigned"&ГТ;dawkinsd&ЛТ;/МЦД:поля&ГТ;
&ЛТ;IDC под имя поля="xTraining"и GT;нет&ЛТ;/МЦД:поля&ГТ;
&ЛТ;IDC под имя поля="xVerification"и GT;нет&ЛТ;/МЦД:поля&ГТ;
&ЛТ;IDC под имя поля="xValidation"&ГТ;да&ЛТ;/МЦД:поля&ГТ;
< idc:имя поля= "temp_xcustomer_eco_number" />
&ЛТ;IDC под названием "имя поля" ="temp_xcustomer_deviation" /&ГТ;
&ЛТ;IDC под названием "имя поля" ="dWfStepName"&ГТ;комплекса&ЛТ;/МЦД:поля&ГТ;
&ЛТ;IDC под названием "имя поля" ="dWfStepID"&ГТ;6168&ЛТ;/МЦД:поля&ГТ;
< idc:имя поля= "dWfStepDescription" />
&ЛТ;IDC под названием "имя поля" ="dWfStepType"&ГТ;:Р:&ЛТ;/МЦД:поля&ГТ;
&ЛТ;IDC под названием "имя поля" ="dWfStepIsAll"и gt;0&ЛТ;/МЦД:поля&ГТ;
&ЛТ;IDC под имя поля="dWfStepWeight"и GT;1&ЛТ;/МЦД:поля&ГТ;
&ЛТ;IDC под названием "имя поля" ="dWfName"&ГТ;Amway_JPS_ARF_WF&ЛТ;/МЦД:поля&ГТ;
< idc:имя поля= "dWfDescription" />
&ЛТ;IDC под названием "имя поля" ="dCompletionDate" /&ГТ;
&ЛТ;IDC под названием "имя поля" ="dWfStatus">По ходу процесса&ЛТ;/МЦД:поля&ГТ;
&ЛТ;IDC под названием "имя поля" ="dWfType"&ГТ;вспомогательного&ЛТ;/МЦД:поля&ГТ;
< idc:имя поля= "dProjectID" />
&ЛТ;IDC под имя поля="dIsCollaboration"и gt;0&ЛТ;/МЦД:поля&ГТ;
< / idc: row>
< / idc:resultset>
< / idc: документ>
< / idc: сервис>
< / SOAP-ENV: Body>
< / SOAP-ENV:конверт>

Я попробовал настроить

XmlNode node = xn.SelectSingleNode("idc:field name='dWfStepName'")
но продолжал получать следующую ошибку
'idc:field name='dWfStepName'' has an invalid token.

Я прошу прощения за то, что задаю простые вопросы. Я очень новичок в XML. Большая часть моего опыта связана с LabView, C++, C# и SQL.

cigwork редактировать

Взгляните сами ... http://www.w3schools.com/xsl/xpath_syntax.asp

В этом случае вы заинтересованы в выборе узлов по атрибутам, а значение-это внутренний текст узла.

XmlNodeList xnList = document.SelectNodes("//idc:field[@name='dWfStepName']", manager);
     int nodes = xnList.Count;

     foreach (XmlNode xn in xnList) {
       Console.WriteLine("Step Name: {0}",
                         xn.InnerText);


Patrice T

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

Рейтинг:
12

AdvancedDNA

ОКОНЧАТЕЛЬНОЕ РЕШЕНИЕ:
Еще раз спасибо cigwork за вашу помощь. Теперь я могу построить список приоритетов, и когда я запускаю вызов SOAP, я могу настроить приоритет по тому, что выпало из списка, что является новым и что все еще там.

Существует больше кода, чем это (около 50 тысяч строк, и этот XML-фрагмент был последним кусочком головоломки!!!).

XmlNodeList xnList = document.SelectNodes("//idc:row", manager);
            int nodes = xnList.Count;
            string step = null;

            foreach (XmlNode xn in xnList)
            {
                var doc = xn.Attributes["dDocName"].Value.ToString();

                XmlNode WFStep = document.SelectSingleNode("//idc:row[@dDocName='"+doc+"']/idc:field[@name='dWfStepName']", manager);
                 
                 //foreach (XmlNode xn1 in xnList1)
                 //{
                     step = WFStep.InnerText.ToString();
                 //}

                listBox1.Items.Add("Doc: " + xn.Attributes["dDocName"].Value.ToString() 
                    + ". Revision: " + xn.Attributes["dRevLabel"].Value.ToString() 
                    + ". Created Date: " + xn.Attributes["dCreateDate"].Value.ToString() 
                    + ". Status: " + xn.Attributes["dStatus"].Value.ToString() 
                    + ". Step: " + step
                    );
            }
        }