Tengo la siguiente respuesta SOAP. Usando mi código, solo pude extraer un elemento. y luego arroja un error de excepción de referencia nula.

¿Cómo extraigo Item-> key y Item-> value en mi diccionario en la función en C #?

A continuación se muestra una parte de la función que utilizo para extraer datos.

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP- ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="urn:Magento" xmlns:ns2="http://xml.apache.org/xml-soap" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
    <ns1:callResponse>
        <callReturn SOAP-ENC:arrayType="ns2:Map[2]" xsi:type="SOAP-ENC:Array">
            <item xsi:type="ns2:Map">
                <item>
                    <key xsi:type="xsd:string">state</key>
                    <value xsi:type="xsd:string">processing</value>
                </item>
                <item>
                    <key xsi:type="xsd:string">status</key>
                    <value xsi:type="xsd:string">processing</value>
                </item>
                <item>
                    <key xsi:type="xsd:string">protect_code</key>
                    <value xsi:type="xsd:string">ba8dd7</value>
                </item>
                <item>
                    <key xsi:type="xsd:string">shipping_firstname</key>
                    <value xsi:type="xsd:string">Roshan</value>
                </item>
                <item>
                    <key xsi:type="xsd:string">billing_name</key>
                    <value xsi:type="xsd:string">Roshan India</value>
                </item>
                <item>
                    <key xsi:type="xsd:string">shipping_name</key>
                    <value xsi:type="xsd:string">Roshan India</value>
                </item>
                <item>
                    <key xsi:type="xsd:string">order_id</key>
                    <value xsi:type="xsd:string">2</value>
                </item>
            </item>
        </callReturn>
    </ns1:callResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Los códigos

 try
        {
            XmlDocument xdoc = new XmlDocument();//xml doc used for xml parsing
            xdoc.LoadXml(content);  // --------> THIS IS WHERE I PASS SOAP RESPONSE
            XmlNamespaceManager nsmgr = new XmlNamespaceManager(xdoc.NameTable);
            nsmgr.AddNamespace("SOAP-ENV:encodingStyle", "http://schemas.xmlsoap.org/soap/encoding/");

            XmlNodeList xNodelst = xdoc.DocumentElement.SelectNodes("//item");
            int nodes = xNodelst.Count;
            dynamic item;
            Dictionary<string, string> items = new Dictionary<string, string>();
            foreach (XmlNode xn in xNodelst)
            {
                XmlNode itemnode = xn["item"];
                if (itemnode != null) {
                    string key = itemnode["key"].InnerText;
                    string value = itemnode["value"].InnerText;
                    items.Add(key, value);
                }

            }
            var ss = items;
            return "";
        }
        catch (Exception e) {
            return e.Message;
        }
1
Roshan Ruzaik 16 oct. 2018 a las 12:10

2 respuestas

La mejor respuesta

Finalmente logré hacer que esto funcionara. Agregué todos los espacios de nombres en la variable del administrador de espacios de nombres. Y usé xPath para navegar a través del XML como se muestra a continuación,

    XmlNodeList xNodelst = xdoc.DocumentElement.SelectNodes("//item[@xsi:type]",nsmgr);

Esto me ayudó a resolver mi problema. Estoy publicando esto aquí en caso de que alguien tenga un problema similar.

¡Salud!

            string soapString = @"<soapenv:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:urn=""urn:Magento""><soapenv:Header/><soapenv:Body><urn:call soapenv:encodingStyle=""http://schemas.xmlsoap.org/soap/encoding/""><sessionId xsi:type=""xsd:string"">"+ssid +@"</sessionId><resourcePath xsi:type=""xsd:string"">sales_order.list</resourcePath><args xsi:type=""xsd:anyType""></args></urn:call></soapenv:Body></soapenv:Envelope>";
            HttpResponseMessage response = await PostXmlRequest("http://localhost/M1/api.php", soapString);
            string content = await response.Content.ReadAsStringAsync();

            XmlDocument xdoc = new XmlDocument();//xml doc used for xml parsing
            xdoc.LoadXml(content);
            XmlNamespaceManager nsmgr = new XmlNamespaceManager(xdoc.NameTable);
            nsmgr.AddNamespace("ns1", "urn:Magento");
            nsmgr.AddNamespace("ns2", "http://xml.apache.org/xml-soap");
            nsmgr.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
            nsmgr.AddNamespace("xsd", "http://www.w3.org/2001/XMLSchema");
            nsmgr.AddNamespace("SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/");
            nsmgr.AddNamespace("encodingStyle", "http://schemas.xmlsoap.org/soap/encoding/");               

            XmlNodeList xNodelst = xdoc.DocumentElement.SelectNodes("//item[@xsi:type]",nsmgr);

            int nodes = xNodelst.Count;                
            Dictionary<int, IDictionary> items = new Dictionary<int, IDictionary>();

            int n = 0;
            foreach (XmlNode xn in xNodelst)
            {
                XmlNode itemnode = xn;
                Dictionary<string, string> itemData = new Dictionary<string, string>();
                foreach (XmlNode xn1 in itemnode)
                {
                    string key = xn1["key"].InnerText;
                    string value = xn1["value"].InnerText;
                    itemData.Add(key, value);
                }                        
                items.Add(n, itemData);
                n++;
            }
 return items;
0
Roshan Ruzaik 16 oct. 2018 a las 13:33

El xml tiene dos niveles del elemento de etiqueta. Por lo tanto, debe asegurarse de tratar cada nivel de la etiqueta del artículo por separado. Usé xml linq para obtener datos y poner los resultados en un diccionario.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
         static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILENAME);
            XElement root = doc.Root;
            XNamespace ns = root.GetDefaultNamespace();

            XElement firstItem = doc.Descendants(ns + "item").FirstOrDefault();

            Dictionary<string, string> dictItems = firstItem.Descendants(ns + "item")
                .GroupBy(x => (string)x.Element("key"), y => (string)y.Element("value"))
                .ToDictionary(x => x.Key, y => y.FirstOrDefault());

        }
    }

}
0
jdweng 16 oct. 2018 a las 09:27