I am trying to read XML using LINQ. Previously I use XMLDocument to read but it gives an error and someone on StackOverflow encourage me to use LINQ.
Below is the code i previously used for the XMLDocument
string soapmessage = #"<?xml version=""1.0"" encoding=""UTF - 8""?>" + "\n" + response.Content;
XmlDocument xml = new XmlDocument();
xml.LoadXml(soapmessage); //loading soap message as string
XmlNamespaceManager manager = new XmlNamespaceManager(xml.NameTable);
manager.AddNamespace("d", "http://tempuri.org/");
manager.AddNamespace("bhr", "http://52.187.127.196:5000/api/gsowebservice.asmx");
XmlNodeList xnList = xml.SelectNodes("//bhr:FourMonthsAhead1Response", manager);
int nodes = xnList.Count;
string Status = xnList[0]["FourMonthsAhead1Result"]["PlantForecastIntervals"]["PlantForecastIntervalNode"]["IntervalStartTime"].InnerText;
Console.WriteLine(Status);
Console.ReadLine();
I am trying to get the <IntervalStartTime> from the first <PlantForecastIntervalNode> into a datetime variable;
Below attaced the XML im trying read:
Below is some of the XML code. I can't paste it here because the code is 2322 lines long so I shortened the code to this.
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<s:Body>
<FourMonthsAhead1Response xmlns="http://tempuri.org/">
<FourMonthsAhead1Result xmlns="LSS.solar.webservice">
<PlantDescription xmlns="http://base.datacontract">*PlantName*</PlantDescription>
<PlantForecastIntervalsCount xmlns="http://base.datacontract">2976</PlantForecastIntervalsCount>
<ForecastStartDate xmlns="http://base.datacontract">2021-10-08T13:35:55.912612</ForecastStartDate>
<ForecastEndDate xmlns="http://base.datacontract">2021-10-08T13:35:55.9126123</ForecastEndDate>
<PlantForecastIntervals xmlns="http://base.datacontract">
<PlantForecastIntervalNode>
<IntervalStartTime>2021-10-01T00:00:00</IntervalStartTime>
<IntervalEndTime>2021-10-01T00:15:00</IntervalEndTime>
<IntervalLength>15</IntervalLength>
<ForecastResultParameter>FourMonthsAhead1</ForecastResultParameter>
<ForecastValue>0</ForecastValue>
<ValueUnit>MW</ValueUnit>
</PlantForecastIntervalNode>
<PlantForecastIntervalNode>
<IntervalStartTime>2021-10-01T00:15:00</IntervalStartTime>
<IntervalEndTime>2021-10-01T00:30:00</IntervalEndTime>
<IntervalLength>15</IntervalLength>
<ForecastResultParameter>FourMonthsAhead1</ForecastResultParameter>
<ForecastValue>0</ForecastValue>
<ValueUnit>MW</ValueUnit>
</PlantForecastIntervalNode>
</PlantForecastIntervals>
</FourMonthsAhead1Result>
</FourMonthsAhead1Response>
</s:Body>
</s:Envelope>
Update
After exploring other threads on StackOverflow I come up with this line below but receive another error of System.UriFormatException: 'Invalid URI: The Uri string is too long.':
XDocument xdoc = XDocument.Load(soapmessage);
var ids = xdoc.Element("FourMonthsAhead1Result")
.Elements("PlantForecastIntervals")
.Elements("<PlantForecastIntervalNode>")
.Select(item => item.Element("IntervalStartTime").Value);
Console.WriteLine(ids);
Try this using LINQ
var response = File.ReadAllText("XMLFile1.xml");
var xe = XElement.Parse(response);
XNamespace ns = "http://base.datacontract";
var obj = xe.Descendants(ns + "PlantForecastIntervals")
.Descendants(ns + "PlantForecastIntervalNode")
.Select(x => x.Element(ns + "IntervalStartTime").Value);
Console.WriteLine(obj);
Look at below solution,
var xmlRead = File.ReadAllText(#"XMLFile1.xml"); /// Add your xml file path
var xElement = XElement.Parse(xmlRead);
XNamespace xNamespace = "http://base.datacontract";
var obj = xElement.Descendants(xNamespace + "PlantForecastIntervals")
.Descendants(xNamespace + "PlantForecastIntervalNode")
.Select(x => x.Element(xNamespace + "IntervalStartTime").Value);
string[] dateTime = obj.ToArray();
foreach (string x in dateTime)
{
Console.WriteLine(x.ToString()); /// it will print time from all IntervalStartTime tags
}
Related
hopefully you can help, this is the SOAP response message that I'm trying to read data from:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<GetVehicleImageDocDescriptorsResponse xmlns="http://kyle/webservices/">
<GetVehicleImageDocDescriptorsResult>
<VehicleImageDocDescriptor>
<Id>91222</Id>
<Epoch>2014-09-12T16:46:22.643</Epoch>
<ImageSetId>172308</ImageSetId>
<ImageMetadata>
<Group>public</Group>
<POV>Beauty Master</POV>
<RightHandDrive>false</RightHandDrive>
<ImageHashCode>1123</ImageHashCode>
</ImageMetadata>
</VehicleImageDocDescriptor>
<VehicleImageDocDescriptor>
<Id>123</Id>
...REPEATING....
And this is the code snippet I have to access the values in those fields:
XDocument doc = XDocument.Parse(getVehicleImageDocDescriptorsResult);
XNamespace ns = "http://kyle/webservices/";
IEnumerable<XElement> responses = doc.Descendants(ns + "VehicleImageDocDescriptor");
foreach (XElement response in responses)
{
pov = (string)response.Element(ns + "POV");
epoch = (string)response.Element(ns + "Epoch");
imageSetId = (string)response.Element(ns + "ImageSetId");
parsedDate = DateTime.Parse(epoch);
}
This works for 'epoch', 'imageSetId' but doesn't work for 'pov', I'm assuming because the 'pov' field is indented another level down it needs an extra level of 'address' if you would, I've been trying different ideas for hours and can't seem to retrieve the value, I've even tried having the full namespace as variable and using that in the 'pov's 'element' bracket but that doesn't work either.
Can anyone please provide me with some ideas?
Many thanks,
Kyle.
In that XML of yours, the POV is nested within ImageMetadata. This should work:
foreach (XElement response in responses)
{
var imageMetadata = response.Element(ns + "ImageMetadata");
var pov = (string)imageMetadata.Element(ns + "POV");
var epoch = (string)response.Element(ns + "Epoch");
var imageSetId = (string)response.Element(ns + "ImageSetId");
var parsedDate = DateTime.Parse(epoch);
}
i have this structure of data:
<?xml version="1.0" encoding="windows-1250"?>
<?xml-stylesheet type="text/xsl" href="usb71105.xsl"?>
<manas:usb xmlns:manas="http://www.manas.info/">
<manas:qr00>
<manas:verzemanas>26052708</manas:verzemanas>
<manas:verzexml>2016.03.29a</manas:verzexml>
<manas:druhtisku>U_Tisk2P/2159405/TRUE</manas:druhtisku>
</manas:qr00>
<manas:qr00>
<manas:verzemanas>26052710</manas:verzemanas>
<manas:verzexml>2016.03.30a</manas:verzexml>
<manas:druhtisku>U_Tisk2P/FALSE</manas:druhtisku>
</manas:qr00>
</manas:usb>
I need to save values of: manas:verzemanas ; manas:verzexml ;
I have this code:
XmlDocument doc = new XmlDocument();
doc.Load("d:\\83116623.XML");
foreach (XmlNode node in doc.DocumentElement)
{
string name = node.Attributes[0].ToString();
}
Have you any ideas please?
You're probably better off with XDocument. Also you need to use the namespace prefix. E.g.:
XNamespace ns = "http://www.manas.info/";
var xdoc = XDocument.Load(#"c:\temp\a\a.xml");
var verze = xdoc.Root.Elements(ns + "qr00")
.Elements(ns + "verzemanas")
.Select(e => e.Value);
verze.ToList().ForEach(v => Console.WriteLine(v));
prints
26052708
26052710
I have an XML file, in this XML you can see the RESPONSE_DATA tag. This tag have some more inner tags. I need to get all the values inside PERSON_DATA tags. Also i need to get all the other value in below xml file.
<?xml version=\"1.0\" encoding=\"utf-16\"?>\r\n
<HUMAN_VERIFICATION xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<RESPONSE_DATA>
<RESPONSE_STATUS>
<ERROR>100</ERROR>
<MESSAGE>successful</MESSAGE>
</RESPONSE_STATUS>
<CONTACT_NUMBER>3120202456011</CONTACT_NUMBER>
<PERSON_DATA>
<NAME>Alex</NAME>
<DATE_OF_BIRTH>10-9-1982</DATE_OF_BIRTH>
<BIRTH_PLACE>Washington</BIRTH_PLACE>
<EXPIRY>2020-12-15</EXPIRY>
</PERSON_DATA>
<CARD_TYPE>idcard</CARD_TYPE>
</RESPONSE_DATA>
</HUMAN_VERIFICATION>
I prefer using Linq to Xml.
var results = doc.Descendants("PERSON_DATA") // Flatten the hierarchy and look for PERSON_DATA
.Select(x=> new
{
NAME = (string)x.Element("NAME"),
DATE_OF_BIRTH = (string)x.Element("DATE_OF_BIRTH"),
BIRTH_PLACE = (string)x.Element("BIRTH_PLACE"),
EXPIRY = (string)x.Element("EXPIRY"),
});
Check the Demo
You can try this code it may be helpful for you.
XmlDocument newdoc = new XmlDocument();
newdoc.InnerXml = " <?xml version=\"1.0\" encoding=\"utf-16\"?><HUMAN_VERIFICATION><RESPONSE_DATA><RESPONSE_STATUS><ERR>100</ERROR><MESSAGE>successful</MESSAGE></RESPONSE_STATUS><CONTACT_NUMBER>3120202456011</ CONTACT _NUMBER><PERSON_DATA><NAME>Alex</NAME><DATE_OF_BIRTH>10-9-1982</DATE_OF_BIRTH><BIRTH_PLACE>Washington</BIRTH_PLACE><EXPIRY>2020-12-15</EXPIRY></PERSON_DATA><CARD_TYPE>idcard</CARD_TYPE></RESPONSE_DATA></HUMAN_VERIFICATION>";
var selectnode = "HUMAN_VERIFICATION/RESPONSE_DATA/PERSON_DATA";
var nodes = newdoc.SelectNodes(selectnode);
foreach (XmlNode nod in nodes)
{
string name = nod["NAME" ].InnerText;
string dob = nod["DATE_OF_BIRTH"].InnerText;
string place = nod["BIRTH_PLACE" ].InnerText;
string expiry = nod["EXPIRY" ].InnerText;
Console.WriteLine("Person: {0} {1} {2} {3}", name, dob, place, expiry);
}
It's really easy and intuitive with System.Xml.Linq.
var xml = "<?xml version=\"1.0\" encoding=\"utf-16\"?>\r\n<HUMAN_VERIFICATION xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\r\n <RESPONSE_DATA>\r\n <RESPONSE_STATUS>\r\n <ERROR>100</ERROR>\r\n <MESSAGE>successful</MESSAGE>\r\n </RESPONSE_STATUS>\r\n <CONTACT_NUMBER>3120202456011</CONTACT_NUMBER>\r\n <PERSON_DATA>\r\n <NAME>Alex</NAME>\r\n <DATE_OF_BIRTH>10-9-1982</DATE_OF_BIRTH>\r\n <BIRTH_PLACE>Washington</BIRTH_PLACE>\r\n <EXPIRY>2020-12-15</EXPIRY>\r\n </PERSON_DATA>\r\n <CARD_TYPE>idcard</CARD_TYPE>\r\n </RESPONSE_DATA>\r\n</HUMAN_VERIFICATION>";
var document = XDocument.Parse(xml);
var name = document.Element("HUMAN_VERIFICATION").Element("RESPONSE_DATA").Element("PERSON_DATA").Element("NAME").Value;
OR
var personData = document.Element("HUMAN_VERIFICATION").Element("RESPONSE_DATA").Element("PERSON_DATA").Elements().ToDictionary(e => e.Name.ToString(), e => e.Value);
I have xml:
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<UpdateMemberHireStatus xmlns="http://tempuri.org/">
<member>
<HireAvailability>
<code>1</code>
<name>פנוי</name>
</HireAvailability>
<HireRejectReason>
<code>2</code>
<name>wow</name>
</HireRejectReason>
<IdNumber>43504349</IdNumber>
<note> </note>
</member>
</UpdateMemberHireStatus>
and I want to use LINQ to access all the nodes in the xml.
Here's what I have tried:
XNamespace ns = "tempuri.org/";
IEnumerable<HireStatus> status = from r in doc.Descendants(ns + "UpdateMemberHireStatus")
.Descendants(ns + "member")
select new HireStatus() { };
return status.ToList();
Use Descendants
var xml = XDocument.Load(XMLStream);
var allEle = xml.Descendants("UpdateMemberHireStatus"); //you can do linq now.
You can use XDocument also in the following way:
string xmlPath = "D://member.xml";
XmlDocument doc = new XmlDocument();
xdoc = XDocument.Load(xmlPath);
doc.LoadXml(xdoc.ToString());
var memberStatus= (from mem in xdoc.Descendants("member")
select mem);
foreach (XElement element in memberStatuses.ToList())
IEnumerable<XNode> nodes = element.Nodes();
var x = XElement.Load(XMLStream);
var all = x.DescendantNodes();
Newbie with XDocuments and Linq, please suggest a solution to retrieve the data from a particular tag in the xml string:
If I have a XML string from webservice response (I formatted xml for ease):
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<GetCashFlowReportResponse xmlns="http://tempuri.org/">
<GetCashFlowReportPdf>Hello!</GetCashFlowReportPdf>
</GetCashFlowReportResponse>
</soap:Body>
</soap:Envelope>
Using the following code, I can get the value only if GetCashFlowReportResponse tag doesn't have "xmlns" attribute. Not sure why? Otherwise, it always return null.
string inputString = "<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><soap:Body><GetCashFlowReportResponse xmlns=\"http://tempuri.org/\"><GetCashFlowReportPdf>Hello!</GetCashFlowReportPdf></GetCashFlowReportResponse></soap:Body></soap:Envelope>"
XDocument xDoc = XDocument.Parse(inputString);
//XNamespace ns = "http://tempuri.org/";
XNamespace ns = XNamespace.Get("http://tempuri.org/");
var data = from c in xDoc.Descendants(ns + "GetCashFlowReportResponse")
select (string)c.Element("GetCashFlowReportPdf");
foreach (string val in data)
{
Console.WriteLine(val);
}
I can't change the web service to remove that attribute. IS there a better way to read the response and get the actual data back to the user (in more readable form)?
Edited:
SOLUTION:
XDocument xDoc = XDocument.Parse(inputString);
XNamespace ns = "http://tempuri.org/";
var data = from c in xDoc.Descendants(ns + "GetCashFlowReportResponse")
select (string)c.Element(ns + "GetCashFlowReportPdf");
foreach (string val in data)
{
Console.WriteLine(val);
}
Note: Even if all the child elements doesn't have the namespace attribute, the code will work if you add the "ns" to the element as I guess childs inherit the namespace from parent (see response from SLaks).
You need to include the namespace:
XNamespace ns = "http://tempuri.org/";
xDoc.Descendants(ns + "GetCashFlowReportResponse")
XName qualifiedName = XName.Get("GetCashFlowReportResponse",
"http://tempuri.org/");
var data = from d in xDoc.Descendants(qualifiedName)
Just ask for the elements using the qualified names:
// create a XML namespace object
XNamespace ns = XNamespace.Get("http://tempuri.org/");
var data = from c in xDoc.Descendants(ns + "GetCashFlowReportResponse")
select (string)c.Element(ns + "GetCashFlowReportPdf");
Note the use of the overloaded + operator that creates a QName with a XML namespace and a local name string.