I am creating a .net core web api method to get the data from xml file based on request. The data is from soap service. Below is request Parameter. So i am searching based on the request parameter.(producer code)
Request------>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:get="http://xyz/business/profile_management_ebe4x1">
<soapenv:Header/>
<soapenv:Body>
<get:GetProducerInfo>
<!--Optional:-->
<GetProducerInfoRequest>
<ProducerCode>IT9559</ProducerCode>
</GetProducerInfoRequest>
</get:GetProducerInfo>
</soapenv:Body>
</soapenv:Envelope>
Below is the response i am looking
Response------->
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<dlwmin:GetProducerInfoResponse xmlns:dlwmin="http://xyz/business/Profile_management_ebe4x1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<GetProducerInfoReply xmlns:ns2="http://xyz/get_access/producer_info" xmlns:ns3="http://yzy/business/profile_reply_ebe4x1">
<Producer>
<ProducerName>MARSH & ABC company</ProducerName>
<ResidentState>TEXAS</ResidentState>
<ResidentCity>MIDLAND</ResidentCity>
<ProducerStatus>Open</ProducerStatus>
<ProducerCode>IT6372</ProducerCode>
<MasterCode>272495</MasterCode>
<NationalCode>174144</NationalCode>
<ProducingBranchCode>ABO</ProducingBranchCode>
<CategoryCode>INT</CategoryCode>
</Producer>
<Producer>
<ProducerName>MARSH & ABC company </ProducerName>
<ResidentState>MICHIGAN</ResidentState>
<ResidentCity>LIVONIA</ResidentCity>
<ProducerStatus>Open</ProducerStatus>
<ProducerCode>IT9559</ProducerCode>
<MasterCode>IT9559</MasterCode>
<NationalCode>174144</NationalCode>
<LegacyCode>0036604-99999</LegacyCode>
<ProducingBranchCode>MBO</ProducingBranchCode>
<CategoryCode>GEN</CategoryCode>
</Producer>
I have created xml file in .net solution
XDocument xdoc = XDocument.Load(Path.Combine(Directory.GetCurrentDirectory(), "ProducerResponse.xml"));
XNamespace ns = "http://xyz/get_access/producer_info";
how i can start read from producer node on request.<producer> always does not not contain equal data. some time it contains 9 or 10. data as it looking from the above data.
TIA
Try xml linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
//put response string here
string response = File.ReadAllText(FILENAME);
XDocument doc = XDocument.Parse(response);
List<Producer> producers = doc.Descendants("Producer").Select(x => new Producer()
{
ProducerName = (string)x.Element("ProducerName"),
ResidentState = (string)x.Element("ResidentState"),
ResidentCity = (string)x.Element("ResidentCity"),
ProducerStatus = (string)x.Element("ProducerStatus"),
ProducerCode = (string)x.Element("ProducerCode"),
MasterCode = (string)x.Element("MasterCode"),
NationalCode = (string)x.Element("NationalCode"),
LegacyCode = (string)x.Element("LegacyCode"),
ProducingBranchCode = (string)x.Element("ProducingBranchCode"),
CategoryCode = (string)x.Element("CategoryCode")
}).ToList();
Dictionary<string, Producer> dict1 = producers
.GroupBy(x => x.ProducerCode, y => y)
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
Dictionary<string, List<Producer>> dict2 = producers
.GroupBy(x => x.ProducerCode, y => y)
.ToDictionary(x => x.Key, y => y.ToList());
}
}
public class Producer
{
public string ProducerName { get; set; }
public string ResidentState { get; set; }
public string ResidentCity { get; set; }
public string ProducerStatus { get; set; }
public string ProducerCode { get; set; }
public string MasterCode { get; set; }
public string NationalCode { get; set; }
public string LegacyCode { get; set; }
public string ProducingBranchCode { get; set; }
public string CategoryCode { get; set; }
}
}
Related
C#:
XElement Xml = null;
var apiResponse = response.Content.ReadAsStringAsync().Result;
Xml = Newtonsoft.Json.JsonConvert.DeserializeObject<XElement>(apiResponse);
XML response from above code:
I'm having errors with Images xml part, while converting it to List,
I tried so many options, Please provide suggestion from below
<root>
<Column1>
<ID>2702</ID>
<Desc>Failed</Desc>
<Address>Florida</Address>
<Date>2019-04-30T23:10:36.79</Date>
<**Images**>
<Image>
<File>1-RRamos.PNG</File>
</Image>
<Image>
<File>RRamos.PNG</File>
</Image>
<Image>
<File>3-RRamos.PNG</File>
</Image>
</**Images**>
</Column1>
</root>
Trying to convert from xml to List from below
public class objClass
{
public string ID{ get; set; }
public string Desc{ get; set; }
public string Address { get; set; }
public DateTime? Date{ get; set; }
//public string[] ImageFileNames { get; set; }
public List<Images> FileName { get; set; }
}
public class FileName
{
public string File{ get; set; }
}
List<objClass> list = Xml.Elements("ID").Select(sv => new objClass()
{
ID= (string)sv.Element("ID"),
Desc= (string)sv.Element("Desc"),
Address = (string)sv.Element("Address"),
Date= (DateTime?)sv.Element("Date"),
//**,Images = (List)sv.Element("Images")**
}).ToList();
From XML response, trying to convert it to List.
You can't use the Newtonsoft.Json library to deserialize from an XML.
Solution 1: Convert XML to list via XPath
Parse XML string to XDocument.
With XPath: "//root/Column1", select the <Column1> element.
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;
using System.Xml.XPath;
var apiResponse = await response.Content.ReadAsStringAsync();
XDocument #Xml = XDocument.Parse(apiResponse);
List<ObjClass> list = #Xml.XPathSelectElements("//root/Column1")
.Select(sv => new ObjClass()
{
ID = (string)sv.Element("ID"),
Desc = (string)sv.Element("Desc"),
Address = (string)sv.Element("Address"),
Date = (DateTime?)sv.Element("Date"),
Images = sv.Element("Images")
.Elements("Image")
.Select(x => new Image
{
File = (string)x.Element("File")
})
.ToList()
})
.ToList();
Solution 2: Deserialize XML
This answer will be a bit complex but work the same as Solution 1.
Write the apiResponse value into MemoryStream.
Deserialize the MemoryStream via XmlSerializer as Root.
Extract root.Column and add into list.
[XmlRoot(ElementName = "root")]
public class Root
{
[XmlElement("Column 1")]
public ObjClass Column { get; set; }
}
public class ObjClass
{
public string ID { get; set; }
public string Desc { get; set; }
public string Address { get; set; }
public DateTime? Date { get; set; }
[XmlArray]
[XmlArrayItem(typeof(Image), ElementName = "Image")]
public List<Image> Images { get; set; }
}
public class Image
{
public string File { get; set; }
}
using System.Xml;
using System.Xml.Serialization;
using System.IO;
var apiResponse = await response.Content.ReadAsStringAsync();
using var stream = new MemoryStream();
using var writer = new StreamWriter(stream);
writer.Write(apiResponse);
writer.Flush();
stream.Position = 0;
XmlSerializer xmlSerializer = new XmlSerializer(typeof(Root));
Root root = (Root)xmlSerializer.Deserialize(stream);
List<ObjClass> list = new List<ObjClass>();
list.Add(root.Column);
Concern:
Use await instead of Task<T>.Result as Task<T>.Result will block the calling thread until it (the task) is completed. With await, the task is waited to be completed asynchronously. Reference: What is the difference between await Task and Task.Result?
public class objClass
{
public string ID { get; set; }
public string Desc { get; set; }
public string Address { get; set; }
public DateTime? Date { get; set; }
public string[] ImageFileNames { get; set; }
}
var list = Xml.Elements("root").Elements("Column1")
.Select(sv => new objClass()
{
ID = (string)sv.Element("ID"),
Desc = (string)sv.Element("Desc"),
Address = (string)sv.Element("Address"),
Date = (DateTime?)sv.Element("Date"),
ImageFileNames = sv.Element("Images")
.Elements("Image")
.Select(i => (string)i.Element("File"))
.ToArray(),
})
.ToList();
<Students>
<Student Name="John">
<Subject SubId="123" Content="History minor subject" Enrolled="true" Percentage="0"/>
<Subject SubId="146" Content="Math major Subject" Enrolled="true" Percentage="0"/>
</Student>
<Student Name="Jim">
<Subject SubId="564" Content="physics medium subject" Enrolled="true" Percentage="0"/>
<Subject SubId="324" Content="Chem small subject" Enrolled="true" Percentage="0"/>
</Student>
<Students>
Problem 1 - I want to search if the person name content John and content has "major" -- > return the Xelememt , I am trying with below query but it is not working for me.
String studentToSearch = "John" and string contentToSearch = "major"
IEnumerable<XElement> student = from st in rootElement.Descendants("Students").Elements("Student")
where st.Attribute("Name").Value.ToString() == studentToSearch && st.Element("Subject").Attribute("Content").Value.ToString().Contains(contentToSearch)
select st;
Problem 2 - I want to search if the person name content John and content has "major", if the percentage for that find it "0"-- > then update it to "80" percentage. Trying with below query
rootElement.Elements("Students")
.Where(x=> x.Element("Student").Value == studentToSearch)
.Where(a => a.Element("Subject").Attributes("Content").ToString().Contains(contentToSearch) && a.Element("Subject").Attribute("Percentage").Value == "0").FirstOrDefault()
.SetAttributeValue("Percentage", 80);
Any suggestion will be helpful ?
Why not just deserialize the xml? You need to use SelectMany.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(FILENAME);
XmlSerializer serializer = new XmlSerializer(typeof(Students));
Students students = (Students)serializer.Deserialize(reader);
var johnMajor = students.Student.SelectMany(x => x.Subject.Where(y => y.Content.Contains("major")).Select(z => new { name = x.Name, Subject = z })).FirstOrDefault();
if (johnMajor.Subject.Percentage == 0) johnMajor.Subject.Percentage = 80;
}
}
public class Students
{
[XmlElement()]
public List<Student> Student { get; set; }
}
public class Student
{
[XmlAttribute()]
public string Name { get; set; }
[XmlElement]
public List<Subject> Subject { get; set; }
}
public class Subject
{
[XmlAttribute()]
public int SubId { get; set; }
[XmlAttribute()]
public string Content { get; set; }
[XmlAttribute()]
public Boolean Enrolled { get; set; }
[XmlAttribute()]
public int Percentage { get; set; }
}
}
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; }
}
}
My goal is to extract the data from the XML. But I have some rather complex XML that is not easily converted to C sharp classes.
The XML looks like this:
<group.........>
<suite....>
<properties>
<property name=....../>
</properties>
<suite type="test">
<suite type="test1">
<suite...>
<suite...>
<suite...>
<case id="1000" name="example">
<properties>
<property ...../>
</properties>
</case>
<case.......>
<properties>
<property ...../>
</properties>
</case>
<case>
<properties>
<property .... />
</properties>
</case>
</suite>
</suite>
</suite>
</suite>
</suite>
</suite>
</group>
I have used an online xml to c sharp convert to create classes, but it does not seem to handle the XML structure correctly.
Update:
The XML comes from NUNIT3. It is the result of the UNIT3 console that is written to an XML document.
Update 2:
I am able to extract data using below code - don't know if there is a more elegant solution:
XElement resultFile = XElement.Load($"{resultFilePathList}");
var dataFromXML = (
from data in resultFile.Descendants("case")
select new
{
caseid = data.Attribute("id").Value,
name = data.Attribute("fullname").Value,
result = data.Attribute("result").Value,
duration = data.Attribute("duration").Value
}
);
Check this code, is as simple as this
using System.Xml.Serialization;
using System.IO;
.......
StreamReader streamer = new StreamReader("yourgroup.xml");
XmlSerializer serializer = new XmlSerializer(typeof(group));
group x = (group)serializer.Deserialize(streamer);
streamer.Close();
And you have do define your classes, somehow like this
public class group {List<suite> suite;}
public class suite
{
public List<suite> suite;
public List<property> properties;
}
Ok, you can add additional annotation if you need specific handling
For instance if there is "case" element, create your class with different name
public class xcase
{
public String id;
public String name;
public Property[] properties;...
}
public class suite
{
[XmlElement(ElementName = "case")]
public xcase[] cases {get; set; }
....
}
Try following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication120
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
XElement group = doc.Root;
Suite rootSuite = new Suite();
Suite.ReadXml(group, rootSuite);
}
}
public class Suite
{
public List<Suite> suites { get; set; }
public List<Case> cases { get; set; }
public Dictionary<string, string> properties { get; set; }
public string type { get; set; }
public static void ReadXml(XElement xparentSuite, Suite parentSuite)
{
foreach (XElement xSuite in xparentSuite.Elements("suite"))
{
parentSuite.type = (string)xSuite.Attribute("type");
if (parentSuite.suites == null) parentSuite.suites = new List<Suite>();
Suite newSuite = new Suite();
parentSuite.suites.Add(newSuite);
XElement properties = xSuite.Element("properties");
if (properties != null)
{
parentSuite.properties = properties.Elements("property")
.GroupBy(x => (string)x.Attribute("name"), y => (string)y)
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
}
parentSuite.cases = xSuite.Elements("case").Select(x => new Case(x)).ToList();
ReadXml(xSuite, newSuite);
}
}
}
public class Case
{
public string id { get; set; }
public string name { get; set; }
public Dictionary<string, string> properties { get; set; }
public Case() { }
public Case(XElement _case)
{
id = (string)_case.Attribute("id");
name = (string)_case.Attribute("name");
properties = _case.Descendants("property")
.GroupBy(x => (string)x.Attribute("name"), y => (string)y)
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
}
}
}
I'm trying to parse this XML Document:
<MPD>
<Period duration="PT0H3M1.63S" start="PT0S">
<AdaptationSet>
<ContentComponent contentType="video" id="1" />
<Representation bandwidth="4190760" codecs="avc1.640028" height="1080" id="1" mimeType="video/mp4" width="1920">
<BaseURL>car-20120827-89.mp4</BaseURL>
</Representation>
<Representation bandwidth="2073921" codecs="avc1.4d401f" height="720" id="2" mimeType="video/mp4" width="1280">
<BaseURL>car-20120827-88.mp4</BaseURL>
</Representation>
</AdaptationSet>
<AdaptationSet>
<ContentComponent contentType="audio" id="2" />
<Representation bandwidth="127236" codecs="mp4a.40.2" id="6" mimeType="audio/mp4" numChannels="2" sampleRate="44100">
<BaseURL>car-20120827-8c.mp4</BaseURL>
</Representation>
<Representation bandwidth="255236" codecs="mp4a.40.2" id="7" mimeType="audio/mp4" numChannels="2" sampleRate="44100">
<BaseURL>car-20120827-8d.mp4</BaseURL>
</Representation>
</AdaptationSet>
</Period>
</MPD>
using this C# code:
var rootDoc = new XmlDocument();
rootDoc.LoadXml(xmlString); // the one from above
var adaptationSets = rootDoc.GetElementsByTagName("AdaptationSet");
if (adaptationSets.Count > 0)
foreach (XmlNode adaptionSet in adaptationSets) // Loop through AdaptionSets
{
// Get the one Node in this AdaptionSet with the ContentComponent-Tag
var contentComponent = adaptionSet.SelectSingleNode("ContentComponent");
if (contentComponent != null)
{
// parse attributes
}
// Get All Nodes in this AdaptionSet with the Representation-Tag
var representations = adaptionSet.SelectNodes("Representation");
if(representations?.Count > 0)
foreach (XmlNode representation in representations)
{
// parse attributes of XmlNode
}
}
It all works except for the XPath queries. I tried a lot of variations with leading "/", "//", "./" and without any leading characters, but it just won't work. What am I doing wrong? I'm not using XPath on a regular basis and I couldn't find anything more than the leading characters I mentioned. Because I've seen it on a lot of other answers on this website I feel like I should mention that I'm explicitly looking for the XPath that will help me solve this, not some Linq variation or an entirely different approach.
Any help is greatly appreciated. Thanks in advance!
I think this solves your problem:
var rootDoc = new XmlDocument();
rootDoc.LoadXml(xmlString); // the one from above
var adaptationSets = rootDoc.SelectNodes("//AdaptationSet");
if (adaptationSets.Count > 0)
foreach (XmlNode adaptionSet in adaptationSets) // Loop through AdaptionSets
{
// Get the one Node in this AdaptionSet with the ContentComponent-Tag
var contentComponent = adaptionSet.SelectSingleNode("./ContentComponent");
if (contentComponent != null)
{
// parse attributes
}
// Get All Nodes in this AdaptionSet with the Representation-Tag
var representations = adaptionSet.SelectNodes("./Representation");
if (representations?.Count > 0)
foreach (XmlNode representation in representations)
{
// parse attributes of XmlNode
}
}
Try using 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 period = doc.Descendants("Period").FirstOrDefault();
MPD mpd = new MPD();
mpd.duration = (string)period.Attribute("duration");
mpd.start = (string)period.Attribute("start");
mpd.adaptions = period.Elements("AdaptationSet").Select(x => new Adaption() {
contentType = (string)x.Element("ContentComponent").Attribute("contentType"),
id = (int)x.Element("ContentComponent").Attribute("id"),
representations = x.Elements("Representation").Select(y => new Representation() {
bandwidth = (int)y.Attribute("bandwidth"),
codecs = (string)y.Attribute("codecs"),
height = (int?)y.Attribute("height"),
id = (int)y.Attribute("id"),
mimeType = (string)y.Attribute("mimeType"),
width = (int?)y.Attribute("width"),
baseURL = (string)y.Descendants("BaseURL").FirstOrDefault()
}).ToList()
}).ToList();
}
}
public class MPD
{
public string duration { get; set; }
public string start { get; set; }
public List<Adaption> adaptions { get; set; }
}
public class Adaption
{
public string contentType { get; set; }
public int id { get; set; }
public List<Representation> representations { get; set; }
}
public class Representation
{
public int bandwidth { get; set; }
public string codecs { get; set; }
public int? height { get; set; }
public int id { get; set; }
public string mimeType { get; set; }
public int? width { get; set; }
public string baseURL { get; set; }
}
}