Unable to use LINQ to XML to loop through xml document - c#

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");
}
}
}

Related

get specific node from XML using XDOCUMENT

I have an XML document with ISO-8859-1 encoding.
I can load the XML with XDOCUMENT, but i can't storage a specific node.
Can somebody help me with this?
The xml:
<?xml version="1.0" ?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<TERMEKADATOutput xmlns="http://xmlns.oracle.com/orawsv/PUPHAX/PUPHAXWS">
<RETURN>
<OBJTERMEKADAT>
<TTT>210037069</TTT>
<TK>OGYI-T-04617/05</TK>
</OBJTERMEKADAT>
</RETURN>
</TERMEKADATOutput>
</soap:Body>
</soap:Envelope>
And the code:
XDocument xmlDoc = null;
using (StreamReader oReader = new StreamReader(#"C:\Users\maruzsama\source\repos\EPPuphax\EPPuphax\asd.xml", Encoding.GetEncoding("ISO-8859-1")))
{
xmlDoc = XDocument.Load(oReader); //this working fine
var result = from q in xmlDoc.Descendants("OBJTERMEKADAT")
select new
{
asd = q.Element("TTT").Value
};
Console.ReadKey();
}
I need the data from the TTT node (210037069)
Try following changes :
XDocument xmlDoc = null;
using (StreamReader oReader = new StreamReader(#"C:\Users\maruzsama\source\repos\EPPuphax\EPPuphax\asd.xml", Encoding.GetEncoding("ISO-8859-1")))
{
xmlDoc = XDocument.Load(oReader); //this working fine
XElement TERMEKADATOutput = xmlDoc.Descendants().Where(x => x.Name.LocalName == "TERMEKADATOutput").First();
XNamespace ns = TERMEKADATOutput.GetDefaultNamespace();
var result = from q in TERMEKADATOutput.Descendants(ns + "OBJTERMEKADAT")
select new
{
asd = q.Element(ns + "TTT").Value
};
Console.ReadKey();
}

creating xml header as in example

I am bad at xml understanding, please help me
this is xml that I need
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:ENRC-IDOC_939_DigiDocs:idm">
<soapenv:Header />
<soapenv:Body>
<urn:mt_digidocs_fees>
This is my code
XmlDeclaration xmlDeclaration = doc.CreateXmlDeclaration( "1.0", "UTF-8", null );
XmlElement root = doc.DocumentElement;
doc.InsertBefore(xmlDeclaration, root);
XmlElement envelope = doc.CreateElement("soapenv","Envelope", "http://schemas.xmlsoap.org/soap/envelope/");
XmlAttribute urn = doc.CreateAttribute("xmlns","urn", "http://www.w3.org/2000/xmlns/");
urn.Value = "urn:ENRC-IDOC_939_DigiDocs:idm";
envelope.Attributes.SetNamedItem(urn);
doc.AppendChild(envelope);
XmlNode soapenvheader = doc.CreateElement("soapenv", "Header", doc.DocumentElement.NamespaceURI);
envelope.AppendChild(soapenvheader);
XmlNode body = doc.CreateElement("soapenv", "Body", doc.DocumentElement.NamespaceURI);
envelope.AppendChild(body);
XmlElement mt_digidocs_fees = doc.CreateElement("mt_digidocs_fees");
mt_digidocs_fees.Prefix = "urn";
body.AppendChild(mt_digidocs_fees);
and this is what I get
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:urn="urn:ENRC-IDOC_939_DigiDocs:idm" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header />
<soapenv:Body>
<mt_digidocs_fees>
So there last Element's name does not contain prefix and namespace addresses are in different order
Thanks in advance
I like using Xml Linq like this :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string ident = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:urn=\"urn:ENRC-IDOC_939_DigiDocs:idm\"></soapenv:Envelope>";
XDocument doc = XDocument.Parse(ident);
XElement envelope = doc.Root;
XNamespace nsUrn = envelope.GetNamespaceOfPrefix("urn");
XNamespace nsSoapenv = envelope.GetNamespaceOfPrefix("soapenv");
XElement header = new XElement(nsSoapenv + "Header");
envelope.Add(header);
XElement body = new XElement(nsSoapenv + "Body");
envelope.Add(body);
XElement fees = new XElement(nsUrn + "mt_digidocs_fees");
body.Add(fees);
}
}
}

C# - Convert XML elements to key value pair in a concatenated string

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; }
}
}

Read XML NodeList

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();
}
}
}

LINQ to XML returns no result

I am using Linq to to parse an XML, but it return no result:
XML:
<?xml version="1.0" encoding="UTF-8"?>
<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>
<downloadInfoResponse xmlns="http://webService">
<downloadInfoReturn>
<city>city</city>
<companyName>company name</companyName>
</downloadInfoReturn>
</downloadInfoResponse>
</soapenv:Body>
</soapenv:Envelope>
Code:
public class Merc
{
public string CompanyName { get; set; }
}
using (XmlReader reader = XmlReader.Create(new StringReader(result)))
{
XDocument doc = XDocument.Load(reader, LoadOptions.SetLineInfo);
List<Merc> m = (from downloadInfoReturn in doc.Descendants("downloadInfoReturn")
select new Merc
{
CompanyName = downloadMerchantInfoReturn.Element("companyName").Value
}).ToList();
}
Is there any other good method to do it? Thank you.
Your XML file contains namespaces thus you need to specify it when perform querying:
XNamespace xn = "http://webService";
doc.Descendants(xn + "downloadInfoReturn")
Because you are missing the namespace while querying the xml, also your class name doesn't match, try the following code, it works on my side.
List<Merc> m = null;
XNamespace ns = "http://webService";
using (XmlReader reader = XmlReader.Create(new StringReader(result)))
{
XDocument doc = XDocument.Load(reader, LoadOptions.SetLineInfo);
m = (from downloadInfoReturn in doc.Descendants(ns + "downloadInfoReturn")
select new Merc
{
CompanyName = downloadInfoReturn.Element(ns+ "companyName").Value
}).ToList<Merc>();
}
Console.WriteLine(m.Count); // this will show 1

Categories