C# Code that Parses the Response from Restful Webservice - c#

I have a webservice that reads the response. It can't parse the response data, because the emsg is null.
Below is the restful webservice, connected to it, and the data returned.
if (response.Body != null && response.Body != "null")
{
var xDocument = XDocument.Parse(response.Body);
var emsg = xDocument.Element("T_OUTPUT").LastNode;
if (emsg != null)
{
var parsedData =
(
from e in xDocument.Element("items").Descendants()
select new ProductPipelineTankInventoryEntity
{
BUKRS = (long)e.Element("BUKRS"),
WERKS = (long)e.Element("WERKS"),
NAME1 = e.Element("NAME1").ToString(),
REGIO = e.Element("REGIO").ToString(),
MATKL = e.Element("MATKL").ToString(),
MATNR = (long)e.Element("MATNR"),
LGORT = e.Element("LGORT").ToString(),
GRDIP = (double)e.Element("GRDIP"),
TRNDATE = DateTime.Parse(e.Element("TRNDATE").ToString()),
VOL_NATURAL = (double)e.Element("VOL_NATURAL"),
GRDIP_RUN = (double)e.Element("GRDIP_RUN"),
VOL_RUNNING = (double)e.Element("VOL_RUNNING")
}
).ToList();
ret.AddRange(parsedData);
}
}
<ns0:YV_PIPELINE_PLANT_DIP_DETAILS.Response xmlns:ns0="urn:sap-com:document:sap:rfc:functions">
<E_MSG/>
<T_OUTPUT>
<item>
<BUKRS>2200</BUKRS>
<WERKS>2222</WERKS>
<NAME1>IOCL,JHARSUGUDA TERMINAL</NAME1>
<REGIO>OR</REGIO>
<MATKL>BULK-MS</MATKL>
<MATNR>16400</MATNR>
<LGORT>T005</LGORT>
<GRDIP>1005.5</GRDIP>
<TRNDATE>2019-08-05</TRNDATE>
<VOL_NATURAL>2048.080</VOL_NATURAL>
<GRDIP_RUN>0825.5</GRDIP_RUN>
<VOL_RUNNING>1686.155</VOL_RUNNING>
</item>
<item>
<BUKRS>2200</BUKRS>
<WERKS>2222</WERKS>
<NAME1>IOCL,JHARSUGUDA TERMINAL</NAME1>
<REGIO>OR</REGIO>
<MATKL>BULK-MS</MATKL>
<MATNR>16400</MATNR>
<LGORT>T006</LGORT>
<GRDIP>173.9</GRDIP>
<TRNDATE>2019-08-05</TRNDATE>
<VOL_NATURAL>776.741</VOL_NATURAL>
<GRDIP_RUN>0915.9</GRDIP_RUN>
<VOL_RUNNING>4130.508</VOL_RUNNING>
</item>
</T_OUTPUT>
</ns0:YV_PIPELINE_PLANT_DIP_DETAILS.Response>
The above code I tried. Below part is of the response output.

You need to have namespaces and change from "items" to "item". For test I read xml from a file instead of a response.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;
using System.Globalization;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
string xmlResponse = File.ReadAllText(FILENAME);
XDocument xDocument = XDocument.Parse(xmlResponse);
XElement emsg = xDocument.Descendants().Where(x => x.Name.LocalName == "T_OUTPUT").FirstOrDefault();
XNamespace ns = emsg.GetDefaultNamespace();
if (emsg != null)
{
var parsedData =
(
from e in xDocument.Descendants(ns + "item")
select new ProductPipelineTankInventoryEntity
{
BUKRS = (long)e.Element(ns + "BUKRS"),
WERKS = (long)e.Element(ns + "WERKS"),
NAME1 = (string)e.Element(ns + "NAME1"),
REGIO = (string)e.Element(ns + "REGIO"),
MATKL = (string)e.Element(ns + "MATKL"),
MATNR = (long)e.Element(ns + "MATNR"),
LGORT = (string)e.Element(ns + "LGORT"),
GRDIP = (double)e.Element(ns + "GRDIP"),
TRNDATE = (DateTime)e.Element(ns + "TRNDATE"),
VOL_NATURAL = (double)e.Element(ns + "VOL_NATURAL"),
GRDIP_RUN = (double)e.Element(ns + "GRDIP_RUN"),
VOL_RUNNING = (double)e.Element(ns + "VOL_RUNNING")
}
).ToList();
}
}
}
public class ProductPipelineTankInventoryEntity
{
public long BUKRS { get; set; }
public long WERKS { get; set; }
public string NAME1 { get; set; }
public string REGIO { get; set; }
public string MATKL { get; set; }
public long MATNR { get; set; }
public string LGORT { get; set; }
public double GRDIP { get; set; }
public DateTime TRNDATE { get; set; }
public double VOL_NATURAL { get; set; }
public double GRDIP_RUN { get; set; }
public double VOL_RUNNING { get; set; }
}
}

Related

LINQ to XML: How to get element value in C#?

I have this XML structure:
<?xml version="1.0" encoding="utf-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope">
<SOAP-ENV:Header>
<dlv:delivery xmlns:dlv="http://schemas.biztalk.org/btf-2-0/delivery">
<dlv:message>
<dlv:messageID>SDID20200921053955</dlv:messageID>
<dlv:sent>2020-09-21T05:39:55</dlv:sent>
</dlv:message>
<dlv:to>
<dlv:address>urn:schindler:SchindlerDraw:prod</dlv:address>
</dlv:to>
<dlv:from>
<dlv:address>urn:schindler:logical-system:CRM</dlv:address>
</dlv:from>
<dlv:from>
<dlv:system>PC1</dlv:system>
</dlv:from>
</dlv:delivery>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<SALESORDER>
<EXTENSIONIN>
<item>
<CONFIRMATIONPRINTDATE />
<CUSTOMEROFFERNOTE />
<CUSTOMERREFERENCE />
</item>
</EXTENSIONIN>
</SALESORDER>
</asx:values>
</asx:abap>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Does anyone know how I can get all the values from the element "item"?
The result should be:
CONFIRMATIONPRINTDATE
CUSTOMEROFFERNOT
CUSTOMERREFERENCE
Thank you in advance.
Use xml linq :
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 delivery = doc.Descendants().Where(x => x.Name.LocalName == "delivery").FirstOrDefault();
XNamespace dlv = delivery.GetNamespaceOfPrefix("dlv");
Envelope envelope = new Envelope();
envelope.messageId = (string)delivery.Descendants(dlv + "messageID").FirstOrDefault();
envelope.sent = (DateTime)delivery.Descendants(dlv + "sent").FirstOrDefault();
envelope.toAddr = (string)delivery.Descendants(dlv + "from").FirstOrDefault().Element(dlv + "address");
envelope.fromAddr = (string)delivery.Descendants(dlv + "to").FirstOrDefault().Element(dlv + "address");
envelope.system = (string)delivery.Descendants(dlv + "system").FirstOrDefault();
envelope.items = doc.Descendants("item").FirstOrDefault().Elements()
.GroupBy(x => x.Name.LocalName, y => (string)y)
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
}
}
public class Envelope
{
public string messageId { get; set; }
public DateTime sent { get; set; }
public string toAddr { get; set; }
public string fromAddr { get; set; }
public string system { get; set; }
public Dictionary<string,string> items { get; set; }
}
}

Read a XML with Linq C# using where condition

I try to make a little Service for my business but it doesn't works.
<item>
<key>12323</key>
<summary></summary>
<reporter username="12313asdf">1232 asdf iii</reporter>
<cusomfields>
<customfield id="customfield_37723" key="xyz">
<customfieldname>First Name</customfieldname>
<customfieldvalues>
<customfieldvalue>Klaus</customfieldvalue>
</customfieldvalues>
</customfield>
//...many customfields
</customfields>
</item>
I created a c# method with this code -> but it doesn't work :(
XDocument doc = XDocument.Load(fileName);
var obj = (from c in doc.Descendants("item")
select new ServiceRequest_NewUser()
{
TicketID = c.Element("key").Value,
Summary = c.Element("summary").Value,
ReporterNT = c.Element("reporter").Attribute("username").Value,
ReporterFull = c.Element("reporter").Value,
FirstName = (from f in c.Descendants("customfields")
where f.Element("customfield")?.Attribute("id")?.Value == "customfield_37723"
select f.Descendants("customfieldvalues").FirstOrDefault()?.Value).FirstOrDefault()
}).ToList();
foreach (var i in obj)
{
var test = i.FirstName;
Console.WriteLine($"{i.TicketID} {i.Summary} {i.ReporterNT} {i.ReporterFull} {i.FirstName}");
}
Where is my fault? I did a alternative version of code in the comment tag. I need to output the value "Klaus".
I thank you in advance for the help.
If you expected to see Klaus in the FirstName, you should write this:
var obj = (from c in doc.Elements("item")
select new
{
TicketID = c.Element("key")?.Value,
Summary = c.Element("summary")?.Value,
ReporterNT = c.Element("reporter")?.Attribute("username")?.Value,
ReporterFull = c.Element("reporter").Value,
FirstName = (from f in c.Descendants("customfields")
where f.Element("customfield")?.Attribute("id")?.Value == "customfield_37723"
select f.Descendants("customfieldvalues").FirstOrDefault()?.Value).FirstOrDefault()
}).ToList();
Try following :
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);
List<Item> items = doc.Descendants("item").Select(x => new Item()
{
key = (string)x.Element("key"),
summary = (string)x.Element("summary"),
usernameText = (string)x.Element("reporter"),
username = (string)x.Element("reporter").Attribute("username"),
fields = x.Descendants("customfield").Select(y => new Field()
{
id = (string)y.Attribute("id"),
key = (string)y.Attribute("key"),
name = (string)y.Element("customfieldname"),
values = y.Descendants("customfieldvalue").Select(z => (string)z).ToList()
}).ToList()
}).ToList();
List<Item> customfield_37723 = items.Where(x => x.fields.Any(y => y.id == "customfield_37723")).ToList();
foreach (Item item in customfield_37723)
{
Console.WriteLine("Item : key = '{0}', summary = '{1}', username Text = '{2}', username = '{3}'",
item.key, item.summary, item.usernameText, item.username);
foreach (Field field in item.fields)
{
Console.WriteLine(" Field : id = '{0}', key = '{1}', name = '{2}', values = '{3}'",
field.id, field.key, field.name, string.Join(",", field.values));
}
}
Console.ReadLine();
}
}
public class Item
{
public string key { get; set; }
public string summary { get; set; }
public string usernameText { get; set; }
public string username { get; set; }
public List<Field> fields { get; set; }
}
public class Field
{
public string id { get; set; }
public string key { get; set; }
public string name { get; set; }
public List<string> values { get; set; }
}
}

breaking out all of the elements in a XML file C#

From another question I had, a answer almost got me there but I have hit a snag.
I need all of the deliveries from a descendant and they are all running together.
Current code I have tried (but it is only getting the first delivery section).
The problem that is being caused with the way I have tried below is that it does not handle the sections that have multiple sections.
I have a semi-working solution that uses data-tables but this is a much cleaner looking solution and I would really like to learn how to get it working like this.
var document = XDocument.Parse(xmlText);
var doc = XDocument.Parse(xmlText);
XNamespace ns0 = doc.Root.GetNamespaceOfPrefix("ns0");
XElement sender = doc.Descendants(ns0 + "SenderNameAndAddress").FirstOrDefault();
string[] senderAddress = sender.Descendants(ns0 + "Address").Elements().Select(x => (string)x).ToArray();
XElement recipientDeliveries = doc.Descendants(ns0 + "RecipientDeliveries").FirstOrDefault();
var results = recipientDeliveries.Elements(ns0 + "Recipient").Select(x => new
{
recipientCode = ((string)x.Descendants(ns0 + "RecipientCode").FirstOrDefault()),
name = (string)x.Descendants(ns0 + "Name").FirstOrDefault(),
address = x.Descendants(ns0 + "Address").Elements().Select(y => (string)y).ToArray(),
deliveries = x.Descendants(ns0 + "Deliveries").Elements().Select(y => (string)y).ToArray(),
deliveryID = (string)x.Descendants(ns0 + "DeliveryID").FirstOrDefault(),
deliveryType = (string)x.Descendants(ns0 + "DeliveryType").FirstOrDefault(),
deliveryRoute = (string)x.Descendants(ns0 + "DeliveryRoute").FirstOrDefault(),
toteID = (string)x.Descendants(ns0 + "ToteID").FirstOrDefault(),
nursingStation = (string)x.Descendants(ns0 + "NursingStation").FirstOrDefault()
}).ToList();
This is the xml sample
<?xml version="1.0" encoding="UTF-8"?>
<ns0:AdvancedShippingNotices xmlns:ns0="http://www.omnicare.com/schema/AdvancedShippingNotices.xsd">
<ns0:ASNID>4129114</ns0:ASNID>
<ns0:CourierID>4SAMEDAY</ns0:CourierID>
<ns0:SenderCode>598</ns0:SenderCode>
<ns0:SenderNameAndAddress>
<ns0:Name>Omnicare of San Diego</ns0:Name>
<ns0:Address>
<ns0:Line1>5601 Oberlin Drive, Suite 124</ns0:Line1>
<ns0:CityTownOrLocality>San Diego</ns0:CityTownOrLocality>
<ns0:StateOrProvince>CA</ns0:StateOrProvince>
<ns0:PostalCode>92121-3709</ns0:PostalCode>
</ns0:Address>
</ns0:SenderNameAndAddress>
<ns0:RecipientDeliveries>
<ns0:Recipient>
<ns0:RecipientCode>1019</ns0:RecipientCode>
<ns0:RecipientNameAndAddress>
<ns0:Name>VILLAGE SQUARE HEALTHCARE CTR</ns0:Name>
<ns0:Address>
<ns0:Line1>1586 W SAN MARCOS BLVD</ns0:Line1>
<ns0:CityTownOrLocality>SAN MARCOS</ns0:CityTownOrLocality>
<ns0:StateOrProvince>CA</ns0:StateOrProvince>
<ns0:PostalCode>92069</ns0:PostalCode>
</ns0:Address>
</ns0:RecipientNameAndAddress>
<ns0:Deliveries>
<ns0:Delivery>
<ns0:DeliveryID>8930798-5</ns0:DeliveryID>
<ns0:DeliveryType>ROUTE</ns0:DeliveryType>
<ns0:DeliveryRoute>R0130</ns0:DeliveryRoute>
<ns0:ToteID>S5-278</ns0:ToteID>
<ns0:NursingStation>2</ns0:NursingStation>
</ns0:Delivery>
<ns0:Delivery>
<ns0:DeliveryID>8934056-1</ns0:DeliveryID>
<ns0:DeliveryType>ROUTE</ns0:DeliveryType>
<ns0:DeliveryRoute>IV</ns0:DeliveryRoute>
<ns0:ToteID>B-132</ns0:ToteID>
<ns0:NursingStation>1</ns0:NursingStation>
</ns0:Delivery>
<ns0:Delivery>
<ns0:DeliveryID>8933908-1</ns0:DeliveryID>
<ns0:DeliveryType>CYCLE</ns0:DeliveryType>
<ns0:DeliveryRoute>CYCLE</ns0:DeliveryRoute>
<ns0:ToteID>B-132</ns0:ToteID>
<ns0:NursingStation>1</ns0:NursingStation>
</ns0:Delivery>
</ns0:Deliveries>
</ns0:Recipient>
<ns0:Recipient>
<ns0:RecipientCode>20366</ns0:RecipientCode>
<ns0:RecipientNameAndAddress>
<ns0:Name>OAKMONT OF ESCONDIDO HILLS</ns0:Name>
<ns0:Address>
<ns0:Line1>3012 BEAR VALLEY PKWY</ns0:Line1>
<ns0:CityTownOrLocality>ESCONDIDO</ns0:CityTownOrLocality>
<ns0:StateOrProvince>CA</ns0:StateOrProvince>
<ns0:PostalCode>92025</ns0:PostalCode>
</ns0:Address>
</ns0:RecipientNameAndAddress>
<ns0:Deliveries>
<ns0:Delivery>
<ns0:DeliveryID>8930798-4</ns0:DeliveryID>
<ns0:DeliveryType>ROUTE</ns0:DeliveryType>
<ns0:DeliveryRoute>R0130</ns0:DeliveryRoute>
<ns0:ToteID>F1-101</ns0:ToteID>
<ns0:NursingStation>AL</ns0:NursingStation>
</ns0:Delivery>
</ns0:Deliveries>
</ns0:Recipient>
</ns0:RecipientDeliveries>
</ns0:AdvancedShippingNotices>
Not sure if you actually use class models or not. But I did a little adjustment for for what's worth (It's will give you more flexibility with the data).
classes :
public class Recipient
{
public int RecipientCode { get; set; }
public RecipientInfo RecipientNameAndAddress { get; set; }
public IList<RecipientDelivery> Deliveries { get; set; }
}
public class RecipientInfo
{
public string Name { get; set; }
public RecipientAddress Address { get; set; }
}
public class RecipientAddress
{
public string Line1 { get; set; }
public string CityTownOrLocality { get; set; }
public string StateOrProvince { get; set; }
public string PostalCode { get; set; }
}
public class RecipientDelivery
{
public string DeliveryID { get; set; }
public string DeliveryType { get; set; }
public string DeliveryRoute { get; set; }
public string ToteID { get; set; }
public string NursingStation { get; set; }
}
then the work :
var doc = XDocument.Parse(file);
XNamespace ns0 = doc.Root.GetNamespaceOfPrefix("ns0");
XElement recipientDeliveries = doc.Descendants(ns0 + "RecipientDeliveries").FirstOrDefault();
var recipients = recipientDeliveries.Descendants(ns0 + "Recipient").ToList();
var RecipientList = new List<Recipient>();
foreach (var item in recipients)
{
var deliveries = item.Descendants(ns0 + "Deliveries").FirstOrDefault();
var deliveriesNodes = deliveries.Descendants(ns0 + "Delivery").ToList();
var recipientInfo = item.Descendants(ns0 + "RecipientNameAndAddress").FirstOrDefault();
var recipientAddress = recipientInfo.Descendants(ns0 + "Address").FirstOrDefault();
var deliverList = new List<RecipientDelivery>();
foreach (var del in deliveriesNodes)
{
var delivery = new RecipientDelivery()
{
DeliveryID = del.Element(ns0 + "DeliveryID").Value,
DeliveryType = del.Element(ns0 + "DeliveryType").Value,
DeliveryRoute = del.Element(ns0 + "DeliveryRoute").Value,
ToteID = del.Element(ns0 + "ToteID").Value,
NursingStation = del.Element(ns0 + "NursingStation").Value
};
deliverList.Add(delivery);
}
var recipient = new Recipient()
{
RecipientCode = Convert.ToInt32(item.Element(ns0 + "RecipientCode").Value),
RecipientNameAndAddress = new RecipientInfo()
{
Name = recipientInfo.Element(ns0 + "Name").Value.ToString(),
Address = new RecipientAddress()
{
Line1 = recipientAddress.Element(ns0 + "Line1").Value.ToString(),
CityTownOrLocality = recipientAddress.Element(ns0 + "CityTownOrLocality").Value.ToString(),
StateOrProvince = recipientAddress.Element(ns0 + "StateOrProvince").Value.ToString(),
PostalCode = recipientAddress.Element(ns0 + "PostalCode").Value.ToString()
},
},
Deliveries = deliverList
};
RecipientList.Add(recipient);
}
Then the whole Recipients will be in RecipientList, which you can use.
A small modification from previous results :
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);
XNamespace ns0 = doc.Root.GetNamespaceOfPrefix("ns0");
XElement sender = doc.Descendants(ns0 + "SenderNameAndAddress").FirstOrDefault();
string[] senderAddress = sender.Descendants(ns0 + "Address").Elements().Select(x => (string)x).ToArray();
XElement recipientDeliveries = doc.Descendants(ns0 + "RecipientDeliveries").FirstOrDefault();
var results = recipientDeliveries.Elements(ns0 + "Recipient").Select(x => new
{
name = (string)x.Descendants(ns0 + "Name").FirstOrDefault(),
address = x.Descendants(ns0 + "Address").Elements().Select(y => (string)y).ToArray(),
deliveries = x.Descendants(ns0 + "Delivery").Select(y => new {
deliveryID = (string)y.Descendants(ns0 + "DeliveryID").FirstOrDefault(),
deliveryType = (string)y.Descendants(ns0 + "DeliveryType").FirstOrDefault(),
deliveryRoute = (string)y.Descendants(ns0 + "DeliveryRoute").FirstOrDefault(),
toteID = (string)y.Descendants(ns0 + "ToteID").FirstOrDefault(),
nursingStation = (string)y.Descendants(ns0 + "NursingStation").FirstOrDefault()
}).ToList()
}).ToList();
}
}
}

XmlSerializer not correct format result

The output i want as below
<SOAP:Envelope xmlns:SOAP='http://schemas.xmlsoap.org/soap/envelope/' >
<SOAP:Body UserGUID = '{redacted}' >
<m:SaveOrder xmlns:m = 'http://www.e-courier.com/schemas/' >
<Order UserID = '1' Notes = 'Signature Requiered' CustomerID = '3' >
</Order >
</m:SaveOrder >
</SOAP:Body >
</SOAP:Envelope >
The output xml that i am getting as my result
<?xml version="1.0"?>
<SOAP:Envelope xmlns:m="http://www.e-courier.com/schemas/" xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP:Body UserGUID="">
<m:SaveOrder >
<m:Order UserID="" Notes="" CustomerID="" />
</m:SaveOrder>
</SOAP:Body>
</SOAP:Envelope>
My XML Class code:
[XmlRoot(ElementName="Order")]
public class Order {
[XmlAttribute(AttributeName="UserID")]
public string UserID { get; set; }
[XmlAttribute(AttributeName="Notes")]
public string Notes { get; set; }
[XmlAttribute(AttributeName="CustomerID")]
public string CustomerID { get; set; }
}
[XmlRoot(ElementName="SaveOrder", Namespace="http://www.e-courier.com/schemas/")]
public class SaveOrder {
[XmlElement(ElementName="Order")]
public Order Order { get; set; }
[XmlAttribute(AttributeName="m", Namespace="http://www.w3.org/2000/xmlns/")]
public string M { get; set; }
}
[XmlRoot(ElementName="Body", Namespace="http://schemas.xmlsoap.org/soap/envelope/")]
public class Body {
[XmlElement(ElementName="SaveOrder", Namespace="http://www.e-courier.com/schemas/")]
public SaveOrder SaveOrder { get; set; }
[XmlAttribute(AttributeName="UserGUID")]
public string UserGUID { get; set; }
}
[XmlRoot(ElementName="Envelope", Namespace="http://schemas.xmlsoap.org/soap/envelope/")]
public class Envelope {
[XmlElement(ElementName="Body", Namespace="http://schemas.xmlsoap.org/soap/envelope/")]
public Body Body { get; set; }
[XmlAttribute(AttributeName="SOAP", Namespace="http://www.w3.org/2000/xmlns/")]
public string SOAP { get; set; }
}
My Code where i am generating xml
var SaveOrder = new ECSaveOrderRequest.Envelope
{
Body = new ECSaveOrderRequest.Body
{
UserGUID = guid,
SaveOrder = new ECSaveOrderRequest.SaveOrder
{
Order = new ECSaveOrderRequest.Order
{
UserID = Uid,
Notes = "",
CustomerID=""
}
}
}
};
var ns = new XmlSerializerNamespaces();
ns.Add("SOAP", "http://schemas.xmlsoap.org/soap/envelope/");
ns.Add("m", "http://www.e-courier.com/schemas/");
var ser = new XmlSerializer(typeof(ECSaveOrderRequest.Envelope));
using (var ms = new MemoryStream())
{
// write the DTO to the MemoryStream
ser.Serialize(ms, SaveOrder, ns);
using (var wc = new WebClient())
{
wc.Encoding = System.Text.Encoding.UTF8;
ms.Position = 0;
StreamReader stream = new StreamReader(ms);
string requestString = stream.ReadToEnd();
var resp = wc.UploadData(ECUrl, ms.ToArray());
}
}
You need to explicitly clear the xml namespace on SaveOrder.Order or the serializer will default to SaveOrder's xml namespace.
Here you go:
using System;
using System.IO;
using System.Text;
using System.Xml.Serialization;
namespace ECSaveOrderRequest
{
/*
* <SOAP:Envelope xmlns:SOAP='http://schemas.xmlsoap.org/soap/envelope/' >
<SOAP:Body UserGUID = '{redacted}' >
<m:SaveOrder xmlns:m = 'http://www.e-courier.com/schemas/' >
<Order UserID = '1' Notes = 'Signature Requiered' CustomerID = '3' >
</Order >
</m:SaveOrder >
</SOAP:Body >
</SOAP:Envelope >*/
public class Order
{
[XmlAttribute(AttributeName = "UserID")]
public string UserID { get; set; }
[XmlAttribute(AttributeName = "Notes")]
public string Notes { get; set; }
[XmlAttribute(AttributeName = "CustomerID")]
public string CustomerID { get; set; }
}
public class SaveOrder
{
[XmlElement(ElementName = "Order", Namespace = "")]
public Order Order { get; set; }
}
public class Body
{
[XmlElement(ElementName = "SaveOrder", Namespace = "http://www.e-courier.com/schemas/")]
public SaveOrder SaveOrder { get; set; }
[XmlAttribute(AttributeName = "UserGUID")]
public string UserGUID { get; set; }
}
[XmlRoot(ElementName = "Envelope", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public class Envelope
{
[XmlElement(ElementName = "Body", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public Body Body { get; set; }
[XmlAttribute(AttributeName = "SOAP", Namespace = "http://www.w3.org/2000/xmlns/")]
public string SOAP { get; set; }
}
class Program
{
static void Main(string[] args)
{
var SaveOrder = new ECSaveOrderRequest.Envelope
{
Body = new ECSaveOrderRequest.Body
{
UserGUID = "{redacted}",
SaveOrder = new ECSaveOrderRequest.SaveOrder
{
Order = new ECSaveOrderRequest.Order
{
UserID = "1",
Notes = "Signature Requiered",
CustomerID = "3"
}
}
}
};
var ns = new XmlSerializerNamespaces();
ns.Add("SOAP", "http://schemas.xmlsoap.org/soap/envelope/");
ns.Add("m", "http://www.e-courier.com/schemas/");
var ser = new XmlSerializer(typeof(ECSaveOrderRequest.Envelope));
var ms = new MemoryStream();
// write the DTO to the MemoryStream
ser.Serialize(ms, SaveOrder, ns);
ms.Position = 0;
var xml = Encoding.UTF8.GetString(ms.GetBuffer());
Console.WriteLine(xml);
Console.ReadKey();
}
}
}
outputs
<?xml version="1.0"?>
<SOAP:Envelope xmlns:m="http://www.e-courier.com/schemas/" xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP:Body UserGUID="{redacted}">
<m:SaveOrder>
<Order UserID="1" Notes="Signature Requiered" CustomerID="3" />
</m:SaveOrder>
</SOAP:Body>
</SOAP:Envelope>
Which is a serialization of the same XML document as
<SOAP:Envelope xmlns:SOAP='http://schemas.xmlsoap.org/soap/envelope/' >
<SOAP:Body UserGUID = '{redacted}' >
<m:SaveOrder xmlns:m = 'http://www.e-courier.com/schemas/' >
<Order UserID = '1' Notes = 'Signature Requiered' CustomerID = '3' >
</Order >
</m:SaveOrder >
</SOAP:Body>
</SOAP:Envelope>
.

Get text for xml node

Sample XML:
<query yahoo:count="1" yahoo:created="2016-03-31T06:43:49Z" yahoo:lang="en-US">
<results>
<channel>
<item>
<yweather:condition code="28" date="Thu, 31 Mar 2016 08:00 AM SAST" temp="58" text="Mostly Cloudy"/>
</item>
</channel>
</results>
</query>
Code:
string weburl = "https://query.yahooapis.com/v1/public/yql?q=select%20item.condition%20from%20weather.forecast%20where%20woeid%20in%20%28select%20woeid%20from%20geo.places%281%29%20where%20text%3D%22Cape%20Town%22%29&format=xml&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys";
var xml = await new WebClient().DownloadStringTaskAsync(new Uri(weburl));
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
XmlElement root = doc.DocumentElement;
XmlNodeList nodes = root.SelectNodes("//query/results/channel/item");
foreach (XmlNode node in nodes)
{
MessageBox.Show(node.InnerXml);
}
I have been struggling to just get the temp and text outputed but I can't find way how to, this is as far as I got.
You can access XML attributes from XmlNode.Attributes property :
var condition = doc.SelectSingleNode("/query/results/channel/item/*");
MessageBox.Show(condition.Attributes["text"].Value);
MessageBox.Show(condition.Attributes["temp"].Value);
Try this....
Usings....
using System.IO;
using System.Net;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
Classes....
[XmlRoot(ElementName = "condition", Namespace = "http://xml.weather.yahoo.com/ns/rss/1.0")]
public class Condition
{
[XmlAttribute(AttributeName = "yweather", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Yweather { get; set; }
[XmlAttribute(AttributeName = "code")]
public string Code { get; set; }
[XmlAttribute(AttributeName = "date")]
public string Date { get; set; }
[XmlAttribute(AttributeName = "temp")]
public string Temp { get; set; }
[XmlAttribute(AttributeName = "text")]
public string Text { get; set; }
}
[XmlRoot(ElementName = "item")]
public class Item
{
[XmlElement(ElementName = "condition", Namespace = "http://xml.weather.yahoo.com/ns/rss/1.0")]
public Condition Condition { get; set; }
}
[XmlRoot(ElementName = "channel")]
public class Channel
{
[XmlElement(ElementName = "item")]
public Item Item { get; set; }
}
[XmlRoot(ElementName = "results")]
public class Results
{
[XmlElement(ElementName = "channel")]
public Channel Channel { get; set; }
}
[XmlRoot(ElementName = "query")]
public class Query
{
[XmlElement(ElementName = "results")]
public Results Results { get; set; }
[XmlAttribute(AttributeName = "yahoo", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Yahoo { get; set; }
[XmlAttribute(AttributeName = "count", Namespace = "http://www.yahooapis.com/v1/base.rng")]
public string Count { get; set; }
[XmlAttribute(AttributeName = "created", Namespace = "http://www.yahooapis.com/v1/base.rng")]
public string Created { get; set; }
[XmlAttribute(AttributeName = "lang", Namespace = "http://www.yahooapis.com/v1/base.rng")]
public string Lang { get; set; }
}
Code...
XmlDocument xmlDocument = new XmlDocument();
try
{
xmlDocument.Load("https://query.yahooapis.com/v1/public/yql?q=select%20item.condition%20from%20weather.forecast%20where%20woeid%20in%20%28select%20woeid%20from%20geo.places%281%29%20where%20text%3D%22Cape%20Town%22%29&format=xml&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys");
string XMLxmlDocument = xmlDocument.InnerXml.ToString();
byte[] BUFXML = ASCIIEncoding.UTF8.GetBytes(XMLxmlDocument);
MemoryStream ms1 = new MemoryStream(BUFXML);
XmlSerializer DeserializerPlaces = new XmlSerializer(typeof(Query));//, new XmlRootAttribute("Query"));
using (XmlReader reader = new XmlTextReader(ms1))
{
Query dezerializedXML = (Query)DeserializerPlaces.Deserialize(reader);
string temp = dezerializedXML.Results.Channel.Item.Condition.Temp;
string text = dezerializedXML.Results.Channel.Item.Condition.Text;
}// Put a break-point here, then mouse-over temp and text, you should have you values (dezerializedXML contains the entire object)
}
catch (System.Exception)
{
throw;
}
I used xml linq along with Regex. I had to fix issues with your xml. I think the main issue was the namespaces.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Text.RegularExpressions;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string xml =
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>" +
"<Root xmlns:yahoo=\"abc\" xmlns:yweather=\"def\">" +
"<query yahoo:count=\"1\" yahoo:created=\"2016-03-31T06:43:49Z\">" +
"yahoo:lang=\"en-US\"><results>" +
"<channel>" +
"<item>" +
"<yweather:condition>" +
"code=\"28\" date=\"Thu, 31 Mar 2016 08:00 AM SAST\" temp=\"58\" text=\"Mostly Cloudy\"/>" +
"</yweather:condition>" +
"</item>" +
"</channel>" +
"</results>" +
"</query>" +
"</Root>";
XDocument doc = XDocument.Parse(xml);
string innertext = doc.Descendants().Where(x => x.Name.LocalName == "condition").Select(y => y.Value).FirstOrDefault();
string pattern = "\\s?(?'name'[^=]+)=\"(?'value'[^\"]+)\"";
MatchCollection matches = Regex.Matches(innertext, pattern);
foreach (Match match in matches)
{
Console.WriteLine("Name : {0}, Value : {1}", match.Groups["name"].Value, match.Groups["value"].Value);
}
Console.ReadLine();
}
}
}

Categories

Resources