Unable to parse and read xml data - c#

I have xml format as below. And trying to read elements from content, product name and product id but unable to. Here is what I have tried so far but no luck. Both of my approaches are not working any help is appreciated.
<source xml:base="https://google.com/api/v1" xmlns="http://www.w3.org/2005/Atom" >
<id>s1</id>
<value>
<id>value1</id>
<version>1.90</version>
<content type="application/xml">
<x:products>
<n:Productname>3M</n:Productname>
<n:ProductId n:type="Int32">97</n:ProductId>
</x:products>
<x:products>
<n:Productname>HD</n:Productname>
<n:ProductId n:type="Int32">99</n:ProductId>
</x:products>
</content>
</value>
</source>
FileStream fs = new FileStream(xmlFile, FileMode.Open, FileAccess.Read);
XmlDocument xmldoc = new XmlDocument();
XmlNodeList xmlnodecontent;
xmldoc.Load(fs);
xmlnodecontent = xmldoc.GetElementsByTagName("content");
for (int i = 0; i < xmlnodecontent.Count; i++)
{
var innerXml =xmlnodecontent[i].ChildNodes.Item(0).InnerXml;
//Trying to read product here
}
//Second approach
var doc = XDocument.Load(xmlFile);
var units = from u in doc.Descendants("value")
select new
{
Id = (int)u.Element("id"),
content = from entry in doc.Descendants("content")
select new
{
product = (int)u.Element("d:Product"),
}
};
foreach (var unit in units)
{
var id = unit.Id;
var content = unit.content;
}

I corrected the xml file and used xml linq (XDocument) to get values
<source xml:base="https://google.com/api/v1" xmlns="http://www.w3.org/2005/Atom" xmlns:x="abc" xmlns:n="def" >
<id>s1</id>
<value>
<id>value1</id>
<version>1.90</version>
<content type="application/xml">
<x:products>
<n:Productname>3M</n:Productname>
<n:ProductId n:type="Int32">97</n:ProductId>
</x:products>
<x:products>
<n:Productname>HD</n:Productname>
<n:ProductId n:type="Int32">99</n:ProductId>
</x:products>
</content>
</value>
</source>
Here is the code :
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 value = doc.Descendants().Where(x => x.Name.LocalName == "value").FirstOrDefault();
XNamespace ns = value.GetDefaultNamespace();
XNamespace xNs = value.GetNamespaceOfPrefix("x");
XNamespace nNs = value.GetNamespaceOfPrefix("n");
var values = doc.Descendants(ns + "value").Select(x => new
{
id = (string)x.Element(ns + "id"),
products = x.Descendants(xNs + "products").Select(y => new
{
name = (string)y.Element(nNs + "Productname"),
id = (string)y.Element(nNs + "ProductId")
}).ToList()
}).ToList();
}
}
}

Related

C# Xdocument Xml get Element

I have a xml file that looks like this:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<GetAllArticlesResponse xmlns="http://www.borger.dk/2009/WSArticleExport/v1">
<GetAllArticlesResult xmlns:a="http://www.borger.dk/2009/WSArticleExport/v1/types" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:ArticleDescription>Test 1</a:ArticleDescription>
<a:ArticleDescription>Test 2</a:ArticleDescription>
</GetAllArticlesResult>
</GetAllArticlesResponse>
</s:Body>
</s:Envelope>
I'm trying to get all the articles, but can't get it to work.
XDocument doc = XDocument.Parse(soapResult);
IEnumerable<XElement> articles = doc.Root.Descendants("a:ArticleDescription");
This has work before, but because the element name as a : then it fails..
Any idea how to fix this.
Thanks for all the inputs.
I ended with::
XNamespace a = "http://www.borger.dk/2009/WSArticleExport/v1/types";
XDocument doc = XDocument.Parse(soapResult);
IEnumerable<XElement> articles = doc.Root.Descendants(a + "ArticleDescription");
List<Article> article = articles.Select(m => new Article()
{
ArticleID = m.Element(a + "ArticleID").Value.ToString(),
ArticleTitle = m.Element(a + "ArticleTitle").Value.ToString(),
ArticleUrl = m.Element(a + "ArticleUrl").Value.ToString(),
LastUpdated = m.Element(a + "LastUpdated").Value.ToString(),
PublishingDate = m.Element(a + "PublishingDate").Value.ToString()
}).ToList();
json = JsonConvert.SerializeObject(article);
Here's an alterante way:
var doc = XDocument.Load(xml);
XNamespace ns1 = "http://schemas.xmlsoap.org/soap/envelope/";
XNamespace ns2 = "http://www.borger.dk/2009/WSArticleExport/v1";
XNamespace ns3 = "http://www.borger.dk/2009/WSArticleExport/v1/types";
var result = doc.Element(ns1 + "Envelope")
.Element(ns1 + "Body")
.Element(ns2 + "GetAllArticlesResponse")
.Element(ns2 + "GetAllArticlesResult")
.Elements(ns3 + "ArticleDescription")
.Select(x => x.Value);
Or
var doc = XDocument.Load(xml);
var envelope = doc.Root;
var body = (XElement)envelope.FirstNode;
var getAllArticlesResponse = (XElement)body.FirstNode;
var getAllArticlesResult = (XElement)getAllArticlesResponse.FirstNode;
var articleDescriptions = getAllArticlesResult.Nodes().Cast<XElement>();
var result = articleDescriptions.Select(x => x.Value);
Here is easiest way using Xml Linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication137
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
string[] description = doc.Descendants().Where(x => x.Name.LocalName == "ArticleDescription").Select(x => (string)x).ToArray();
}
}
}
The prefix a: is a short-for of the namespace name "http://www.borger.dk/2009/WSArticleExport/v1/types", you can see that where the prefix is declared.
You can use namespace-aware XName's when querying:
var descriptions = doc.Root.Descendants(
XName.Get("ArticleDescription", "http://www.borger.dk/2009/WSArticleExport/v1/types"));
Of course you could store the namespaces you want in variables, you don't have to type them out every time.
You can also just look at the local names, if you're not worried about collisions.
var descriptions = doc.Root.Descendants().Where(x => x.Name.LocalName == "ArticleDescription");

c# - Select node in xmlDocument

I have an XML with this structure:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:Dossiers xmlns:ns2="http://www.dat.de/vxs" source="SD3" type="completeEvaluation">
<ns2:Dossier>
<ns2:Vehicle>
<ns2:VehicleIdentNumber>aaaaaaaaaa</ns2:VehicleIdentNumber>
<ns2:Equipment>
<ns2:OriginalEquipmentValueGross origin="dat">16206.00</ns2:OriginalEquipmentValueGross>
<ns2:SeriesEquipment>
<ns2:EquipmentPosition>
<ns2:DatEquipmentId>15201</ns2:DatEquipmentId>
<ns2:Description>lorem ipsum</ns2:Description>
</ns2:EquipmentPosition>
<ns2:EquipmentPosition>
<ns2:DatEquipmentId>17602</ns2:DatEquipmentId>
<ns2:Description>lorem ipsum</ns2:Description>
</ns2:EquipmentPosition>
...
</ns2:SeriesEquipment>
</ns2:Vehicle>
<ns2:Vehicle>
....
</ns2:Vehicle>
</ns2:Dossier>
</ns2:Dossiers>
With this code I have obtained the ns2:VehicleIdentNumber value:
XmlDocument xml = new XmlDocument();
xml.LoadXml(xmlFileContent);
var xmlNodeList = xml.GetElementsByTagName("ns2:Vehicle");
foreach (XmlElement xmlElement in xmlNodeList)
{
var telaio = xmlElement["ns2:VehicleIdentNumber"];
}
but how can I get ns2:OriginalEquipmentValueGross value and ns2:Description value?
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 root = doc.Root;
XNamespace ns2 = root.GetNamespaceOfPrefix("ns2");
var results = doc.Descendants(ns2 + "Vehicle").Select(x => new
{
vehicleIdentNumber = (string)x.Element(ns2 + "VehicleIdentNumber"),
originalEquipmentValueGross = (string)x.Descendants(ns2 + "OriginalEquipmentValueGross").FirstOrDefault()
}).ToList();
}
}
}
It should be more or less the same of what you already have:
var xmlNodeList = xml.GetElementsByTagName("ns2:Vehicle");
foreach (XmlElement xmlElement in xmlNodeList)
{
var telaio = xmlElement["ns2:VehicleIdentNumber"];
var equipment = xmlElement["ns2:Equipment"];
var originalEquipmentValueGross = equipment["ns2:OriginalEquipmentValueGross"].InnerText;
foreach (XmlElement equipmentPosition in equipment["ns2:SeriesEquipment"].GetElementsByTagName("ns2:EquipmentPosition"))
{
var description = equipmentPosition["ns2:Description"].InnerText;
}
}

Reading XML with namespace and repeating nodes

I have the following XML:
<resource>
<description>TTT</description>
<title>TEST</title>
<entity xmlns="TdmBLRuPlUz.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="TdmBLRuPlUz.xsd TdmBLRuPlUz.xsd">
<UzdProd>
<row>
<F_DAUDZ>50</F_DAUDZ>
<BR_DAUDZ/>
<DAUDZ>50</DAUDZ>
<U_DAUDZ/>
<NKODS>ST2.0_014_023</NKODS>
</row>
</UzdProd>
<UzdMat>
<row>
<NKODS>SAG 2.0_014_150</NKODS>
<NNOSAUK>Sagatave 2.0mm*0.14*150m</NNOSAUK>
<PK_VIEN>1</PK_VIEN>
<DAUDZ>0.077</DAUDZ>
<F_DAUDZ>0.077</F_DAUDZ>
</row>
</UzdMat>
</entity>
</resource>
And this is my C# code:
XNamespace ns = "TdmBLRuPlUz.xsd";
XDocument doc = XDocument.Parse(xml);
foreach (XElement element in doc.Descendants(ns + "row"))
{
Console.WriteLine(element.Element(ns + "NKODS").Value);
string NKODS = element.Element(ns + "NKODS").Value;
string F_DAUDZ = element.Element(ns + "F_DAUDZ").Value;
string DAUDZ = element.Element(ns + "DAUDZ").Value;
}
What I need is to read values from the XML nodes NKODS, F_DAUDZ and DAUDZ.
The problem is that there are repeating nodes with those names and with this code it gives me the last ones which are under UzdMat node. What would be the way to get the values for these nodes under UzdProd?
I tried to change row to UzdProd, but that didn't work.
You need to read the specific row you want rather than looping through all of them. For example:
var prodRow = doc.Descendants(ns + "UzdProd").Elements(ns + "row").Single();
var matRow = doc.Descendants(ns + "UzdMat").Elements(ns + "row").Single();
var prodNkods = (string) prodRow.Element(ns + "NKODS");
var matNkods = (string) matRow.Element(ns + "NKODS");
See this fiddle for a working demo.
See if this works :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication25
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
XElement entity = doc.Descendants().Where(x => x.Name.LocalName == "entity").FirstOrDefault();
XNamespace ns = entity.GetDefaultNamespace();
var results = entity.Elements().Select(x => new {
uzd = x.Name.LocalName,
dict = x.Descendants(ns + "row").Elements().GroupBy(y => y.Name.LocalName, z => (string)z)
.ToDictionary(y => y.Key, z => z.FirstOrDefault())
}).ToList();
}
}
}

How to read xml file in c# with specific attribute

I have an xml file with attribute
xmlns="http://www.reservwire.com/namespace/WebServices/Xml">
When I remove this attribute, then I can read each tag. If I don't remove attribute I receive error message "Object refrence not set to instance of object"
My C# code:
XmlDocument xml = new XmlDocument();
xml.Load(Server.MapPath("~/HotelSearchCriteria/PrepareBooking.xml"));
string CommmitLevel = xml.DocumentElement
.SelectSingleNode("/BookingCreate/CommitLevel")
.InnerText;
My XML:
<BookingCreate xmlns="http://www.reservwire.com/namespace/WebServices/Xml">
<Authority>
<Org>danco</Org>
<User>xmltest</User>
<Password>xmltest</Password>
<Language>en</Language>
<Currency>EUR</Currency>
<TestDebug>false</TestDebug>
<Version>1.26</Version>
</Authority>
<QuoteId>17081233-3</QuoteId>
<HotelStayDetails>
<Room>
<Guests>
<Adult title="Mr" first="djkvb" last="jkj" />
<Adult title="Mr" first="jfs" last="kjdjs" />
</Guests>
</Room>
</HotelStayDetails>
<HotelSearchCriteria>
<AvailabilityStatus>allocation</AvailabilityStatus>
<DetailLevel>basic</DetailLevel>
</HotelSearchCriteria>
<CommitLevel>prepare</CommitLevel>
</BookingCreate>
What to do to read xml with xmlns attribute? It is necessary for me to have xmlns attribute.
You need to specify the namespace, by using a namespace manager. This should work
XmlDocument bookingXml = new XmlDocument();
bookingXml.Load("PrepareBooking.xml");
XmlNamespaceManager ns = new XmlNamespaceManager(bookingXml.NameTable);
ns.AddNamespace("booking", "http://www.reservwire.com/namespace/WebServices/Xml");
var commitLevel = bookingXml.SelectSingleNode("//booking:BookingCreate//booking:CommitLevel", ns).InnerText;
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 bookingCreate = doc.Descendants().Where(x => x.Name.LocalName == "BookingCreate").FirstOrDefault();
XNamespace ns = bookingCreate.GetDefaultNamespace();
var results = doc.Descendants(ns + "BookingCreate").Select(x => new {
org = (string)x.Descendants(ns + "Org").FirstOrDefault(),
user = (string)x.Descendants(ns + "User").FirstOrDefault(),
password = (string)x.Descendants(ns + "Password").FirstOrDefault(),
language = (string)x.Descendants(ns + "Language").FirstOrDefault(),
currency = (string)x.Descendants(ns + "Currency").FirstOrDefault(),
testDebug = (Boolean)x.Descendants(ns + "TestDebug").FirstOrDefault(),
version = (string)x.Descendants(ns + "Version").FirstOrDefault(),
quoteId = (string)x.Element(ns + "QuoteId"),
guests = x.Descendants(ns + "Adult").Select(y => new {
title = (string)y.Attribute("title"),
first = (string)y.Attribute("first"),
last = (string)y.Attribute("last")
}).ToList(),
availability = (string)x.Descendants(ns + "AvailabilityStatus").FirstOrDefault(),
detailLevel = (string)x.Descendants(ns + "DetailLevel").FirstOrDefault()
}).FirstOrDefault();
}
}
}

How to get XmlElement from XmlNodeList in C#?

Below is sample of my XML file
<?xml version="1.0" encoding="UTF-8"?>
<summary>
<testresult>
<result value="10" name="long">100</result>
<result value="12" name="short">200</result>
<result value="14" name="long">300</result>
</testresult>
<testresult>
<result value="10" name="short">50</result>
<result value="12" name="short">60</result>
<result value="14" name="long">70</result>
</testresult>
</summary>
I need to get attribute values for result elements.
I done it using foreach loop as below.
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(item.Value);
XmlNodeList nodelist = xmlDoc.SelectNodes("//testresult");
for (int i = 0; i < nodelist.Count; i++)
{
foreach (XmlElement child in nodelist[i])
{
if (child.HasAttributes)
{
result.Add(child.Attributes["value"].Value); //This is working fine.
}
}
}
My ultimate goal is to identify the name and get value if name = "long" only.
for that I need to get the value of name Attribute.
I need to do that without using foreach loop. Any suggestion to achieve my task inside the for loop ?
Thanks.
You could parse your xml easy with XDocument:
var xDoc = XDocument.Load(#"YourXmlFile");
var result = xDoc.Descendants("result")
.Where(x=>x.Attribute("name").Value=="long")
.Select(x=>x.Value);
If you can use LINQ to XML then you even can get results as integers
var xdoc = XDocument.Load(item.Value);
var results = from r in xdoc.Descendants("result")
where (string)r.Attribute("name") == "long"
select (int)r.Attribute("value");
Output:
[10, 14, 14]
If you have to use XmlDocument
var result = from XmlElement tr in xmlDoc.SelectNodes("//testresult")
from XmlElement r in tr
where r.Attributes["name"].Value == "long"
select r.Attributes["value"].Value;
You can also provide more preciese XPath
var result = from XmlElement r in xmlDoc.SelectNodes("//testresult/result[#name='long']")
select r.Attributes["value"].Value;
Using xml linq to get all the values
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication43
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
var results = doc.Descendants("testresult").Select(x => new {
result = x.Elements("result").Select(y => new {
value = (int)y.Attribute("value"),
name = (string)y.Attribute("name"),
text = (int)y
}).ToList()
}).ToList();
}
}
}

Categories