How to parse XML with namespace - c#

Bonjour,
I have an xml doc:
<ns2:feeds xmlns:ns2="XXXX" xmlns="XXXXX" version="3.0">
<ns2:feed>
<name>XXX</name>
</ns2:feed>
<ns2:feed>
<name>XXX</name>
</ns2:feed>
<ns2:feed>
<name>XXX</name>
</ns2:feed>
</ns2:feeds>
How can I use LinqToXml to get a list of Name properties? nothing I try seems to work...
var doc = XDocument.Load(#"feed.xml");
var names = doc
.XPathSelectElements("/*/*[localname()='feeds']") //What should the Xpath be, here?
.Select(p => new
{
Name = p.Descendants("name").First().Value
})
.ToList();
Is there a simple way to achieve this?

You can do this
XNamespace ns = XNamespace.Get("XXXX");
var listOfNames = doc.Descendants(ns + "feed")
.Select(x => x.Elements().First().Value).ToList();
+1 for lazyberezovsky's answer. If you need to specify the element name (name in this case) or you could have multiple name elements then you need to add a second namespace for those elements.
XNamespace ns2 = XNamespace.Get("XXXXX");
var listOfNames = doc.Root.Descendants(ns2 + "name").Select(x => x.Value).ToList();

With XPathSelectElements you should provide namespace manager in order to use namespaces in XPath query:
var manager = new XmlNamespaceManager(new NameTable());
manager.AddNamespace("ns2", "XXXX");
manager.AddNamespace("ns", "XXXXX"); // default namespace
var names = from n in xdoc.XPathSelectElements("//ns2:feed/ns:name", manager)
select (string)n;
Without XPath you should use XNamespace when providing name of node to find:
XNamespace ns = "XXXXX";
XNamespace ns2 = "XXXX";
var names = from f in xdoc.Descendants(ns2 + "feed")
select (string)f.Element(ns + "name");

To get rid of namespaces in XLinQ queries, use similar method mentioned below:
String xml_string = #"<ns2:feeds xmlns:ns2=""XXXX"" xmlns=""XXXXX"" version=""3.0"">
<ns2:feed>
<name>XXX</name>
</ns2:feed>
<ns2:feed>
<name>YYY</name>
</ns2:feed>
<ns2:feed>
<name>ZZZ</name>
</ns2:feed>
</ns2:feeds>";
var query = XElement.Parse(xml_string).Descendants()
.Where(c => c.Name.LocalName.ToString() == "name")
.ToArray();
foreach (String item in query)
{
Console.WriteLine(item);
}

Related

Unknown error? for XDocument.Descendants [duplicate]

I have this xml string:
<a:feed xmlns:a="http://www.w3.org/2005/Atom"
xmlns:os="http://a9.com/-/spec/opensearch/1.1/"
xmlns="http://schemas.zune.net/catalog/apps/2008/02">
<a:link rel="self" type="application/atom+xml" href="/docs" />
<a:updated>2014-02-12</a:updated>
<a:title type="text">Chickens</a:title>
<a:content type="html">eat 'em all</a:content>
<sortTitle>Chickens</sortTitle>
... other stuffs
<offers>
<offer>
<offerId>8977a259e5a3</offerId>
... other stuffs
<price>0</price>
... other stuffs
</offer>
</offers>
... other stuffs
</a:feed>
and want to get value of <price> but here in my codes:
XDocument doc = XDocument.Parse(xmlString);
var a = doc.Element("a");
var offers = a.Element("offers");
foreach (var offer in offers.Descendants())
{
var price = offer.Element("price");
var value = price.Value;
}
doc.Element("a"); returns null. I tried removing that line offers is also null. what is wrong in my code and how to get value of price? thanks
Here is correct way to get prices:
var xdoc = XDocument.Parse(xmlString);
XNamespace ns = xdoc.Root.GetDefaultNamespace();
var pricres = from o in xdoc.Root.Elements(ns + "offers").Elements(ns + "offer")
select (int)o.Element(ns + "price");
Keep in mind that your document have default namespace, and a is also namespace.
Get the namespace somehow, like
XNameSpace a = doc.Root.GetDefaultNamespace();
or, probably better:
XNameSpace a = doc.Root.GetNamespaceOfPrefix("a");
and then use it in your queries:
// to get <a:feed>
XElement f = doc.Element(a + "feed");
You can also set the namespace from a literal string, but then avoid var.
var xDoc = XDocument.Load(filename);
XNamespace ns = "http://schemas.zune.net/catalog/apps/2008/02";
var prices = xDoc
.Descendants(ns + "offer")
.Select(o => (decimal)o.Element(ns + "price"))
.ToList();
a is a namespace. To get the feed element try this:
XDocument doc = XDocument.Parse(xmlString);
XNamespace a = "http://www.w3.org/2005/Atom";
var feed = doc.Element(a + "feed");

Looping through xmlnodes using Xdocument

I have an xml string like this
<Test>
<ConnectionParameters>
<ConnectionParameter DisplayName="asd" Id="cgfh" IsPassword="false" IsRequired="true"> </ConnectionParameter>
<ConnectionParameter DisplayName="asdasd" Id="fgh" IsPassword="false" IsRequired="true"></ConnectionParameter>
<ConnectionParameter DisplayName="asdasd" Id="hdfh" IsPassword="false" IsRequired="true"></ConnectionParameter>
<ConnectionParameter DisplayName="asdad" Id="dfgdf" IsPassword="false" IsRequired="true"> </ConnectionParameter>
</ConnectionParameters>
</Test>
How can I loop through each "ConnectionParameter" tag inorder to get the attributes like Id,DisplayName etc using xdocument?
I tried like this,
XDocument xdoc = new XDocument();
xdoc= XDocument.Parse(fileContent);
var saveResult = from b in xdoc.Descendants("ConnectionParameters")
select new
{
success = (string)b.Element("ConnectionParameter").Attribute("Id").Value ?? string.Empty,
};
But it only returns the first node only
You're currently looping through all the ConnectionParameters elements (of which there's only one) and selecting the first ConnectionParameter element (using the Element call). You want to just loop through the ConnectionParameter elements:
// Note the lack of creating a new XDocument for no reason
XDocument xdoc = XDocument.Parse(fileContent);
var saveResult = from b in xdoc.Descendants("ConnectionParameter")
select new
{
success = (string) b.Attribute("Id") ?? ""
};
Or to avoid creating an anonymous type for no obvious reason, and using plain "dot notation" as the query expression isn't helping you much:
XDocument xdoc = XDocument.Parse(fileContent);
var saveResult = xdoc.Descendants("ConnectionParameter")
.Select(b => (string) b.Attribute("Id") ?? "");
If you prefer to make the parent element names explicit, you could use:
XDocument xdoc = XDocument.Parse(fileContent);
var saveResult = xdoc.Element("Test")
.Element("ConnectionParameters")
.Descendants("ConnectionParameter")
.Select(b => (string) b.Attribute("Id") ?? "");
Or:
XDocument xdoc = XDocument.Parse(fileContent);
var saveResult = xdoc.Root
.Element("ConnectionParameters")
.Descendants("ConnectionParameter")
.Select(b => (string) b.Attribute("Id") ?? "");
Load your xml into xDocument, then you can do something like this (can't remember exact syntax)
xDoc.Root.Descendants("ConnectionParameters").Attribute("DisplayName").Value;

XDocument.Element returns null when parsing an xml string

I have this xml string:
<a:feed xmlns:a="http://www.w3.org/2005/Atom"
xmlns:os="http://a9.com/-/spec/opensearch/1.1/"
xmlns="http://schemas.zune.net/catalog/apps/2008/02">
<a:link rel="self" type="application/atom+xml" href="/docs" />
<a:updated>2014-02-12</a:updated>
<a:title type="text">Chickens</a:title>
<a:content type="html">eat 'em all</a:content>
<sortTitle>Chickens</sortTitle>
... other stuffs
<offers>
<offer>
<offerId>8977a259e5a3</offerId>
... other stuffs
<price>0</price>
... other stuffs
</offer>
</offers>
... other stuffs
</a:feed>
and want to get value of <price> but here in my codes:
XDocument doc = XDocument.Parse(xmlString);
var a = doc.Element("a");
var offers = a.Element("offers");
foreach (var offer in offers.Descendants())
{
var price = offer.Element("price");
var value = price.Value;
}
doc.Element("a"); returns null. I tried removing that line offers is also null. what is wrong in my code and how to get value of price? thanks
Here is correct way to get prices:
var xdoc = XDocument.Parse(xmlString);
XNamespace ns = xdoc.Root.GetDefaultNamespace();
var pricres = from o in xdoc.Root.Elements(ns + "offers").Elements(ns + "offer")
select (int)o.Element(ns + "price");
Keep in mind that your document have default namespace, and a is also namespace.
Get the namespace somehow, like
XNameSpace a = doc.Root.GetDefaultNamespace();
or, probably better:
XNameSpace a = doc.Root.GetNamespaceOfPrefix("a");
and then use it in your queries:
// to get <a:feed>
XElement f = doc.Element(a + "feed");
You can also set the namespace from a literal string, but then avoid var.
var xDoc = XDocument.Load(filename);
XNamespace ns = "http://schemas.zune.net/catalog/apps/2008/02";
var prices = xDoc
.Descendants(ns + "offer")
.Select(o => (decimal)o.Element(ns + "price"))
.ToList();
a is a namespace. To get the feed element try this:
XDocument doc = XDocument.Parse(xmlString);
XNamespace a = "http://www.w3.org/2005/Atom";
var feed = doc.Element(a + "feed");

How to Select XML node, given only the attribute name

I have an XML file as follow
<NODE1 attribute1 = "SomeValue" attribute2 = "SomeOtherValue" />
<NODE2 attribute3 = "SomeValue" attribute4 = "SomeOtherValue" />
Now I am given only the attribute name say "attribute3". How can I get the name of node?
Add the following namespace at the top of your file:
using System.Xml.Linq;
And try this (assuming that input.xml is the path to your XML file):
var xml = XDocument.Load("input.xml");
string nodeName;
var node = xml.Descendants()
.FirstOrDefault(e => e.Attribute("attribute3") != null);
if (node != null)
nodeName = node.Name.LocalName;
With LINQ to XML:
XDocument xdoc = XDocument.Load(path_to_xml);
var nodes = xdoc.Descendants().Where(e => e.Attribute("attribute3") != null);
Or with XPath (as Marvin suggested):
var nodes = xdoc.XPathSelectElements("//*[#attribute3]");
Both queries will return collection of XElement nodes which have attribute attribute3 defined. You can get first of them with FirstOrDefault. If you want to get just name, use node.Name.LocalName.
UPDATE: I do not recommend you to use XmlDocument, but if you already manipulating this xml document, then loading it second time with XDocument could be inefficient. So, you can select nodes with XPathNavigator:
var doc = new XmlDocument();
doc.Load(path_to_xml);
var naviagator = doc.CreateNavigator();
var nodeIterator = naviagator.Select("//*[#attribute3]");
try in this way
string nodeName;
if(Node.Attributes.Cast<XmlAttribute>().Any(x => x.Name == "attribute3"))
{
nodeName=Node.Name;
}

Getting value of an attribute within namespace

I am trying to process the following XML:
<rif:Rif xmlns:rif="rif" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" rif:numeroRif="XYZXYZXYZ">
<rif:Nombre>Nombre</rif:Nombre>
<rif:AgenteRetencionIVA>SI</rif:AgenteRetencionIVA>
<rif:ContribuyenteIVA>SI</rif:ContribuyenteIVA>
<rif:Tasa />
</rif:Rif>
An I am using the next code:
XDocument doc = XDocument.Parse(result);
var q = from item in doc.Descendants()
let attributeType = item.Attribute("AgenteRetencionIVA").Value
select item;
I have problems to get the attribute rif:AgenteRetencionIVA. How do I to do it?
Looks like tou need to specify custom namespace:
string xml = #"...";
XName nameRif = "rif";
XDocument doc = XDocument.Parse(xml);
var q = from item in doc.Descendants()
let attributeType = item.Attribute(nameRif + "AgenteRetencionIVA")
select item.Value;
var a = q.ToArray();

Categories

Resources