I Have below XML as an input
<Details>
<PAY>
<Mode>xyz</Mode>
<REMARKS>no</REMARKS>
</PAY>
<data>
<Customer>
<Participant>
<Participant1FirstName>aaaa</Participant1FirstName>
<Participant1LastName>zzzz</Participant1LastName>
</Participant>
<Participant>
<Participant2FirstName>bbbb</Participant2FirstName>
<Participant2LastName>yyyy</Participant2LastName>
</Participant>
<Participant>
<Participant3FirstName>cccc</Participant3FirstName>
<Participant3LastName>xxxx</Participant3LastName>
</Participant>
</Customer>
</data>
</Details>
Desired output :
String strOutput = "|Participant1FirstName = aaaa|Participant1LastName = zzzz|; |Participant2FirstName = bbbb|Participant2LastName = yyyy|; |Participant3FirstName = cccc|Participant3LastName = xxxx|"
SO far, I have tried parsing XML string into XDocument, and thinking of using Linq to get the desired output, but don't know the way forward.
Input :
string strXML = "<Details> <PAY> <Mode>xyz</Mode> <REMARKS>no</REMARKS> </PAY> <data> <Customer> <Participant> <Participant1FirstName>aaaa</Participant1FirstName> <Participant1LastName>zzzz</Participant1LastName> </Participant> <Participant> <Participant2FirstName>bbbb</Participant2FirstName> <Participant2LastName>yyyy</Participant2LastName> </Participant> <Participant> <Participant3FirstName>cccc</Participant3FirstName> <Participant3LastName>xxxx</Participant3LastName> </Participant> </Customer> </data></Details>"
XDocument xdoc = new XDocument();
xdoc = XDocument.Parse(strXML);
Edit
Any way I can get desired output from below XML ?
<Details>
<PAY>
<Mode>xyz</Mode>
</PAY>
<data>
<Customer>
<Participant>
<Participant1>
<Participant1FirstName>aaaa</Participant1FirstName>
<Participant1LastName>zzzz</Participant1LastName>
</Participant1>
<Participant2>
<Participant2FirstName>bbbb</Participant2FirstName>
<Participant2LastName>yyyy</Participant2LastName>
</Participant2>
<Participant>
</Customer>
</data>
</Details>
You could do it like this
XDocument xdoc = new XDocument();
xdoc = XDocument.Parse(strXML);
var values = xdoc.Descendants("Participant").Elements()
.Select(x => x.Name + " = " + x.Value).ToList();
string result = string.Join("|", values);
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<Particapant> participants = doc.Descendants("Participant").Select(x => new Particapant()
{
firstName = (string)x.Elements().FirstOrDefault(),
lastName = (string)x.Elements().LastOrDefault()
}).ToList();
string output = string.Join(";", participants
.Select(x => string.Format("|ParticipantFirstName = {0}|ParticipantLastName = {1}|", x.firstName, x.lastName)));
}
}
public class Particapant
{
public string firstName { get; set; }
public string lastName { get; set; }
}
}
Related
Given the following XML file:
<root>
<country>
<name></name>
<locationOU>null</location>
</country>
<country>
<name>Sweden</name>
<locationOU>Some Value</locationOU>
</country>
<country>
<name>Lithuania</name>
<locationOU>Some Value</locationOU>
</country>
<country>
<name>Belgium</name>
<locationOU>Some Value</locationOU>
</country>
</root>
How do I get the value of locationOU based on name value eg. name = Sweden?
You can work with XPath via XPathSelectElement(XNode, String).
using System.Xml.Linq;
using System.Xml.XPath;
// Read XML file
XDocument root = XDocument.Load(/* Your XML file path */);
// Read XML from string
// XDocument root = XDocument.Parse(xml);
XElement result = root.XPathSelectElement("/root/country[name='Sweden']");
string locationOU = result.Element("locationOU").Value;
Demo # .NET Fiddle
I like using xml linq with a dictionary :
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication40
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
Dictionary<string, string> dict = doc.Descendants("country")
.GroupBy(x => (string)x.Element("name"), y => (string)y.Element("locationOU"))
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
string sweedenLocation = dict["Sweden"];
}
}
}
XDocument doc = XDocument.Parse(XML_TEXT);
XElement rootElement = doc.XPathSelectElement("root");
var countries = rootElement?.Descendants().Where(e => e.Name.LocalName.Equals("country"));
var yourCountry = countries.Descendants().FirstOrDefault(d => d.Name.LocalName.Equals("locationOU") && d.Value == "Sweden");
You can use XPath with above answers #Yong Shun
Or You can use DataSet as bellow:
DataSet ds=new DataSet();
ds.readXml(filename);
DataTable dt=ds.Tables[0];
string name="Sweden";
foreach(DataRow dr in dt.Select(String.Format("name='{0}'",name))
{
string locationOU=dr["locationOU"].toString();
}
I'm trying to get the element values of the following XML document using LINQ but I'm getting "Object reference not set to an instance of an object.";
XML:
<soapenv:Envelope xmlns:soapenv=http://schemas.xmlsoap.org/soap/envelope/
xmlns:xsd=http://www.w3.org/2001/XMLSchema xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance>
<soapenv:Body>
<ns1:GetContactResponse soapenv:encodingStyle=http://schemas.xmlsoap.org/soap/encoding/ xmlns:ns1=http://DefaultNamespace>
<GetContactReturn xsi:type="ns2:Response" xmlns:ns2=http://getContact.contact.V300>
<Contact xsi:type="ns3:Contact" xmlns:ns3=http://_contact.contact.V300>
<Address xsi:type="xsd:string">123 test</Address>
<Address2 xsi:type="xsd:string"/>
<City xsi:type="xsd:string">Los Angeles</City>
<CountryCode xsi:type="xsd:string">US</CountryCode>
<StateCode xsi:type="xsd:string">CA</StateCode>
<ZipCode xsi:type="xsd:string">90001</ZipCode>
</Contact>
<Errors soapenc:arrayType="ns4:Error[0]" xsi:type="soapenc:Array" xmlns:ns4=http://response.base.V300 xmlns:soapenc=http://schemas.xmlsoap.org/soap/encoding//>
<IsSuccessful xsi:type="xsd:boolean">true</IsSuccessful>
<RecordCount xsi:type="xsd:double">1.0</RecordCount>
</GetContactReturn>
</ns1:GetContactResponse>
</soapenv:Body>
</soapenv:Envelope>
I'm using the following to loop through:
using (StreamReader rd = new StreamReader(services.GetResponseStream()))
{
var ServiceResult = rd.ReadToEnd();
XDocument xdoc = new XDocument();
xdoc = XDocument.Parse(ServiceResult);
var xDocResult = (from x in xdoc.Descendants("Contacts")
select new Location
{
Address = x.Element("Address").Value,
Address2 = x.Element("Address2").Value,
city = x.Element("City").Value,
statecode = x.Element("StateCode").Value,
zipcode = x.Element("ZipCode").Value
});
}
I'm assuming it's because there is no root. How do I get the values of the individual elements?
Your xml has lots of errors. I'm using StringReader. You should replace with StreamReader. Here is correction
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<ns1:GetContactResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="http://DefaultNamespace">
<GetContactReturn xsi:type="ns2:Response" xmlns:ns2="http://getContact.contact.V300">
<Contact xsi:type="ns3:Contact" xmlns:ns3="http://_contact.contact.V300">
<Address xsi:type="xsd:string">123 test</Address>
<Address2 xsi:type="xsd:string"/>
<City xsi:type="xsd:string">Los Angeles</City>
<CountryCode xsi:type="xsd:string">US</CountryCode>
<StateCode xsi:type="xsd:string">CA</StateCode>
<ZipCode xsi:type="xsd:string">90001</ZipCode>
</Contact>
<Errors soapenv:arrayType="ns4:Error[0]" xsi:type="soapenc:Array" xmlns:ns4="http://response.base.V300 xmlns:soapenc=http://schemas.xmlsoap.org/soap/encoding"/>
<IsSuccessful xsi:type="xsd:boolean">true</IsSuccessful>
<RecordCount xsi:type="xsd:double">1.0</RecordCount>
</GetContactReturn>
</ns1:GetContactResponse>
</soapenv:Body>
</soapenv:Envelope>
Here is the c# code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
string xml = File.ReadAllText(FILENAME);
StringReader reader = new StringReader(xml);
XDocument doc = XDocument.Load(reader);
XElement contact = doc.Descendants().Where(x => x.Name.LocalName == "Contact").FirstOrDefault();
XNamespace ns = contact.GetDefaultNamespace();
string address = (string)contact.Element(ns + "Address");
string address2 = (string)contact.Element(ns + "Address2");
string city = (string)contact.Element(ns + "City");
string country = (string)contact.Element(ns + "CountryCode");
string state = (string)contact.Element(ns + "StateCode");
string zip = (string)contact.Element(ns + "ZipCode");
}
}
}
I've created a program to retrieve data from a database and convert it to XML. It returns a list of 24 objects that I created:
<?xml version = "1.0" encoding = "utf-16"
<ArrayOfData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Data>
<interval>01</interval>
<num>12345</num>
<id>ABC123 </id>
<type>LETTER</type>
<party>1</party>
<amount>-10</amount>
</Data>
<Data>
<interval>02</interval>
<num>12345</num>
<id>ABC123 </id>
<type>LETTER</type>
<party>1</party>
<amount>-11</amount>
</Data>
<Data>
<interval>03</interval>
<num>12345</num>
<id>ABC123 </id>
<type>LETTER</type>
<party>1</party>
<amount>-12</amount>
</Data>
<Data>
<interval>04</interval>
<num>12345</num>
<id>ABC123 </id>
<type>LETTER</type>
<party>1</party>
<amount>-13</amount>
</Data>
Basically the data goes on with incrementing intervals by 1 up to 24.
What I am looking for is to look for what is duplicate and just concatenate them into one child, and then to look for what differs and create a different element for it but keep them everything in one child. How can I write the XML to do this? Example:
<Data>
<num>12345</num>
<id>ABC123 </id>
<type>LETTER</type>
<party>1</party>
<details>
<interval>01</interval>
<amount>-10</amount>
</details>
<details>
<interval>02</interval>
<amount>-11</amount>
</details>
<details>
<interval>03</interval>
<amount>-12</amount>
</details>
<details>
<interval>04</interval>
<amount>-13</amount>
</details>
</Data>
I want to create a function that returns this XML. The parameters in my current function now are just there to get the data using those parameters. Here's how I generate the XML now:
public IActionResult CreateXML(int num, int id)
{
string xml = "";
var temp = (from x in Context.InternalData.AsNoTracking() where (x.num == num && x.id == id) select x).ToList();
using (var stringwrite = new Utf8StringWriter())
{
var serializer = new XmlSerializer(temp.GetType());
serializer.Serialize(stringwrite, temp);
xml = stringwrite.ToString();
StringReader reader = new StringReader(stringwriter.ToString());
reader.ReadLine(); //skips the UTF-16 header
XDocument doc = XDocument.Load(reader);
XElement arrayOfData = doc.Root;
List<XElement> newData = new List<XElement>();
var parties = doc.Descendants("Data")
.GroupBy(x => (string)x.Element("id"))
.ToList();
foreach (var party in parties)
{
XElement template = party.First();
List<XElement> details = party.Select(x => new XElement("details", new object[] {
new XElement("interval", (string)x.Element("interval")),
new XElement("amount", (string)x.Element("amount"))
})).ToList();
template.Element("interval").Remove();
template.Element("amount").Remove();
template.Add(details);
newData.Add(template);
}
arrayOfData.ReplaceAll(newData);
return Ok(arrayOfData);
}
}
I am new to this and have never worked with generating XML before. Any help would be greatly appreciated!
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)
{
string xml = File.ReadAllText(FILENAME);
StringWriter stringwriter = new StringWriter();
stringwriter.Write(xml);
StringReader reader = new StringReader(stringwriter.ToString());
reader.ReadLine(); //skips the UTF-16 header
XDocument doc = XDocument.Load(reader);
XElement arrayOfData = doc.Root;
List<XElement> newData = new List<XElement>();
var parties = doc.Descendants("Data")
.GroupBy(x => (string)x.Element("id"))
.ToList();
foreach (var party in parties)
{
XElement template = party.First();
List<XElement> details = party.Select(x => new XElement("details", new object[] {
new XElement("interval", (string)x.Element("interval")),
new XElement("amount", (string)x.Element("amount"))
})).ToList();
template.Element("interval").Remove();
template.Element("amount").Remove();
template.Add(details);
newData.Add(template);
}
arrayOfData.ReplaceAll(newData);
}
}
}
I am trying to parse an XML response from a REST call. I can read the XML just fine with my stream reader but when I try to select the first node, it brings back nothing. Here is my XML:
<?xml version="1.0" encoding="UTF-8" standalone="true"?>
<slot_meta_data xmlns:ns2="http://www.w3.org/2005/Atom">
<product id="MDP">
<name>MDP</name>
</product>
<product id="CTxP">
<name>CTxP</name>
</product>
<product id="STR">
<name>STR</name>
</product>
<product id="ApP">
<name>ApP</name>
<slot>
<agent_id>-1111</agent_id>
<agent_name>ApP</agent_name>
<index_id>-1</index_id>
<alias>App Alias</slot_alias>
</slot>
</product>
<product id="TxP">
<name>TxP</name>
<slot>
<agent_id>2222</agent_id>
<agent_name>App2</agent_name>
<index_id>-1</index_id>
<alias>App2 Alias</slot_alias>
</slot>
</product>
</slot_meta_data>
Here is my code
string newURL = "RESTURL";
HttpWebRequest request = WebRequest.Create(newURL) as HttpWebRequest;
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
StreamReader reader = new StreamReader(response.GetResponseStream());
XmlDocument xdoc = new XmlDocument();
xdoc.Load(response.GetResponseStream());
XmlNodeList list = xdoc.SelectNodes("/slot_meta_data[#*]");
foreach (XmlNode node in list)
{
XmlNode product = node.SelectSingleNode("product");
string name = product["name"].InnerText;
string id = product["id"].InnerText;
Console.WriteLine(name);
Console.WriteLine(id);
Console.ReadLine();
}
When I debug list, it has a count of 0.
Using xml linq
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication22
{
class Program
{
const string FILENAME = #"c:\TEMP\TEST.XML";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
var results = doc.Descendants("product").Select(x => new {
name = (string)x.Element("name"),
slot = x.Elements("slot").Select(y => new {
agent_id = (int)y.Element("agent_id"),
agent_name = (string)y.Element("agent_name"),
index_id = (int)y.Element("index_id"),
slot_alias = (string)y.Element("slot_alias")
}).FirstOrDefault()
}).ToList();
}
}
}
Aim:
- Deserialize data from an xml document and storing it as an array.
- Avoiding manually assigning the data to different strings.
- The xml document will be manually generated
public void DeserializeObject(string filename)
{
try
{
XmlSerializer deserializer = new XmlSerializer(typeof(string[]));
FileStream fs = new FileStream(filename, FileMode.Open);
string[] XmlData = (string[])deserializer.Deserialize(fs);
foreach (string p in XmlData)
{
Console.WriteLine(p);
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
The XML document is as follows
<?xml version="1.0" encoding="utf-8"?>
<Mapping xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Products>
<Product>
<software>Seiko</software>
</Product>
<Product>
<hardware>Martina</hardware>
</Product>
</Products>
</Mapping>
Thank you, found this solution
<?xml version="1.0" encoding="utf-8" ?>
<Locations>
<Location Name="Location1" IP="127.0.0.1"></Location>
<Location Name="Location2" IP="127.0.0.1"></Location>
<Location Name="Location3" IP="127.0.0.1"></Location>
<Location Name="Location4" IP="127.0.0.1"></Location>
<Location Name="Location5" IP="127.0.0.1"></Location>
</Locations>
using System.Xml.Linq;
class Program
{
static void Main(string[] args)
{
string[] strarr = GetStringArray("Locations.xml");
foreach (string str in strarr)
{
Console.WriteLine(str);
}
}
public static string[] GetStringArray(string url)
{
XDocument doc = XDocument.Load(url);
var locations = from l in doc.Descendants("Location")
select (string)l.Attribute("Name");
return locations.ToArray();
}
}
Try this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication38
{
class Program
{
static void Main(string[] args)
{
string input =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<Mapping xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">" +
"<Products>" +
"<Product>" +
"<software>Seiko</software>" +
"</Product>" +
"<Product>" +
"<hardware>Martina</hardware>" +
"</Product>" +
"</Products>" +
"</Mapping>";
XDocument doc = XDocument.Parse(input);
var results = doc.Descendants("Product").Select(x =>
x.Elements().Select(y => new { type = y.Name, value = (string)y }).ToList()
).SelectMany(z => z).ToList();
var groups = results.GroupBy(x => x.type).ToList();
}
}
}
You need to generate a class from your sample XML.
You can use the xsd.exe to generate a .xsd and from that create a .cs file.
The you need to add this type to your XmlSerializer
See this answer: Generate C# class from XML
XmlSerializer deserializer = new XmlSerializer(typeof(Mapping)); <- Created class type here.
If all you want to do is get the data form the XML-document as an array of strings, you can use XmlDocument to load in the data
XmlDocument doc = new XmlDocument();
doc.Load("file.xml");
Then you can find the nodes you need using an xPath expression:
XmlNodeList nodelist = doc.SelectNodes(...);