C# XElement Get Attribute with a Namespace - c#

I have a number of XElements, but their "href" attribute has a namespace. When I try to get it, it returns null.
<link xlink:href="The/href" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="a/location">A value</link>
I have tried:
XElement linkEl = doc.Root.Element("link");
string hrefValue = linkEl.Attribute("href").Value //null;
I have also tried adding the namespace to the "href" like "xlink:href" in Attribute(), but this results in an error. Anyone know how to perform this magic?

Try this one:
XDocument doc = XDocument.Parse(#"<link xlink:href=""The/href"" xmlns:xlink=""http://www.w3.org/1999/xlink"" xmlns=""a/location"">A value</link>");
XNamespace ab = "http://www.w3.org/1999/xlink";
string hrefValue = doc.Root.Attribute(ab + "href").Value;

For your sample xml you can't find your element by using its Name it must be the LocalName of the element.
To get element by LocalName here is the sample:
var linkElement = doc.Root.Elements().Where(e => e.Name.LocalName == "link").FirstOrDefault();
var linkAttribute = linkElement.Attributes().Where(a => a.Name.LocalName == "href").FirstOrDefault();
var hrefValue = linkAttribute.Value;

Related

XmlDocument loping (foreach) reomving NameSpace "xmlns"

hey guys I had XML file and I was using XDocument to write on it and using the next void remove the namespace
string path = Server.MapPath(xmlpath);
XDocument doc = XDocument.Load(path)
XElement root = new XElement("url");
foreach (var node in doc.Root.Descendants()
.Where(n => n.Name.NamespaceName == ""))
{
node.Attributes("xmlns").Remove();
node.Name = node.Parent.Name.Namespace + node.Name.LocalName;
}
this function works 100% with the XDocument now I changed
XDocument oldDoc = XDocument.Load(path);// the old doucument
XmlDocument newDoc = new XmlDocument();//the new document
I need a function that allows me to make loping and remove the namespace xmlns from my nodes the same one like above thanks a lot for your time's guys and thanks a lot for reading my question
You were very close, just had to use XMLDocument.CreateElement(string Name) overload which returns a XMLNode and then use .InnerText property to set your value
var mainRoot = doc.DocumentElement; //urlset element
var urlRoot = doc.CreateElement("url"); //create url element
var VidooTree = urlRoot.AppendChild(doc.CreateElement(a, ""));
urlRoot.AppendChild(doc.CreateElement("loc", "http:/domain/site.com"));
VidooTree.AppendChild(doc.CreateElement(b)).InnerText="imgur";
VidooTree.AppendChild(doc.CreateElement(c)).InnerText= "videoTitle";
VidooTree.AppendChild(doc.CreateElement("video:description")).InnerText= "videoDec";
VidooTree.AppendChild(doc.CreateElement(d)).InnerText= "VideoApi";
VidooTree.AppendChild(doc.CreateElement(m)).InnerText= "duration";
VidooTree.AppendChild(doc.CreateElement(nn)).InnerText= "2050-11-05T19:20:30+08:00";
VidooTree.AppendChild(doc.CreateElement(e)).InnerText= "watched";
VidooTree.AppendChild(doc.CreateElement(k)).InnerText= "date";
VidooTree.AppendChild(doc.CreateElement(f)).InnerText= "yes";
VidooTree.AppendChild(doc.CreateElement(g)).InnerText="No";
VidooTree.AppendChild(doc.CreateElement(h)).InnerText= "VideoKindName";
urlRoot.AppendChild(VidooTree);
mainRoot.AppendChild(urlRoot);
Output
<url xmlns="">
<loc xmlns="http:/domain/site.com" />
<video>
<thumbnail_loc>imgur</thumbnail_loc>
<title>videoTitle</title>
<description>videoDec</description>
<content_loc>VideoApi</content_loc>
<duration>duration</duration>
<expiration_date>2050-11-05T19:20:30+08:00</expiration_date>
<view_count>watched</view_count>
<publication_date>date</publication_date>
<family_friendly>yes</family_friendly>
<live>No</live>
<category>VideoKindName</category>
</video>
</url>

LINQ xml finding nodes returns null

I try to parse an xml file with XDocument class, with criteria that if the child node matches a given string, its parent node is selected.
<SalesQuotes xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://api.some.com/version/1">
<Pagination>
<NumberOfItems>2380</NumberOfItems>
<PageSize>200</PageSize>
<PageNumber>1</PageNumber>
<NumberOfPages>12</NumberOfPages>
</Pagination>
<SalesQuote>
<Guid>825634b9-28f5-4aa7-98e7-5e4a4ed6bc6a</Guid>
<LastModifiedOn>2018-01-09T12:23:56.6133445</LastModifiedOn>
<Comments>Please note:
installation is not included in this quote
</Comments>
</SalesQuote>
</SalesQuotes>
I tried using
var contents = File.ReadAllText(path: "test1.xml");
var doc = XDocument.Parse(contents);
var root = doc.Root;
var sq = root.Elements("SalesQuote");//return null
var theQuote = root.Elements("SalesQuote").Where(el => el.Element("Guid").Value == "825634b9-28f5-4aa7-98e7-5e4a4ed6bc6a");//return null
var theAlternativeQuote =
from el in doc.Descendants("SalesQuote").Elements("Guid")
where el.Value == "825634b9-28f5-4aa7-98e7-5e4a4ed6bc6a"
select el;//return null
I can't seem to find what's wrong.
Any help is much appreciated! Thanks.
You ignored the namespace bro.
Do remove the xmlns attribute in your XML or try this:
var contents = File.ReadAllText("XMLFile1.xml");
var doc = XDocument.Parse(contents);
var root = doc.Root;
XNamespace ns = "http://api.some.com/version/1";
var sq = root.Descendants(ns + "SalesQuotes"); //return null
var theQuote = root.Elements(ns + "SalesQuote")
.Where(el => el.Element(ns + "Guid").Value == "825634b9-28f5-4aa7-98e7-5e4a4ed6bc6a"); //return null
var theAlternativeQuote =
from el in doc.Descendants(ns + "SalesQuote").Elements(ns + "Guid")
where el.Value == "825634b9-28f5-4aa7-98e7-5e4a4ed6bc6a"
select el; //return null
If you are not too concerned about keeping your current implementation, you could consider using a Typed DataSet and load your XML into fully typed, structured objects.
Querying those objects with Linq will be more straight forward than what I see in your current implementation.
You might also find this useful:
SO Question: Deserialize XML Document to Objects
yap, you're missing the namespace that you can grab with document.Root.GetDefaultNamespace()
// Load
var document = XDocument.Parse(xml);
var xmlns = document.Root.GetDefaultNamespace();
// Find
var query = from element in document
.Descendants(xmlns + "SalesQuote")
.Elements(xmlns + "Guid")
where element.Value == "825634b9-28f5-4aa7-98e7-5e4a4ed6bc6a"
select element;

C# split xml innertext or parse innerxml

I have an XML file with a structure similar to this
<entry name="something">
<members>
<member>aaa</member>
<member>bbb</member>
</members>
</entry>
<entry name="something_else">
<members>
<member>ccc</member>
<member>ddd</member>
</members>
</entry>
I need to be able to get the values out of each of the member nodes to store in a datatable. if i use the innertext property, it concatenates the values (aaabbb). there is nothing discernible to split the string on. I can also use the inner XML but then i just get a string with the XML structure (aaa bbb<\member>)
What is the best way to get each value out of the XML elements and store it in a string array?
here is what I have been trying.
foreach (XmlNode grpNode in GrpList)
{
subNode = grpNode.Attributes["name"];
if (subNode != null)
{
Obj = grpNode.Attributes["name"].Value;
}
subNode = grpNode["members"];
if (subNode != null)
{
string innerXml = string.Empty;
innerXml = grpNode["members"].InnerXml.ToString();
string[] tempArrary = innerXml.Split(new char[] {'>', '<'});
}
}
You can use Xpath to iterate through Entry nodes and get the members within it like this
string xml = "<root><entry name='something'>" +
"<members>" +
"<member>aaa</member>" +
"<member>bbb</member>" +
"</members>" +
"</entry>" +
"<entry name='something_else'>" +
"<members>" +
"<member>ccc</member>" +
"<member>ddd</member>" +
"</members>" +
"</entry></root>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
var memsList = doc.SelectNodes("//entry");
foreach (XmlNode a in memsList)
{
Console.WriteLine(a.Attributes["name"].Value);
var memList = a.SelectNodes("members/member");
foreach(XmlNode x in memList)
Console.WriteLine(x.InnerText);
}
You need to iterate the child elements within members, so something like:
foreach (var node in grpNode["members"].ChildNodes)
{
var value = node.InnerText;
}
That said, you would be better off using LINQ to XML unless you have some specific reason to use XmlDocument. This gives you much more expressive code, for example:
var doc = XDocument.Parse(xml);
var something = doc.Descendants("entry")
.Where(e => (string)e.Attribute("name") == "something")
.Single();
var somethingMembers = something.Descendants("member")
.Select(e => e.Value)
.ToArray();
This should do the trick:
XDocument xdoc = XDocument.Load(#"Path/to/file");
var result = xdoc.Descendants("member").Select (x => x.Value).ToArray();
Result:
Demo Code
the xml you've provided isn't valid. But assuming you just want the inner text of all member nodes into a string array, I'd just use Linq-To-Xml (XDocument):
var results = XDocument.Parse(xmlString)
.Descendants("member")
.Select(m => m.Value)
.ToArray();
Even though you're using the old XmlDocument API, by throwing in an .OfType<XmlNode>() you can convert an XmlNodeList to a generic enumerable and thereby mix in some linq and lambda syntax, for instance:
var tempArrary = subNode.SelectNodes("member").OfType<XmlNode>().Select(n => n.InnerText).ToArray();

get xml node value from xml string

I have xml which contain xml namespace. i need to get value from its xml node
<personxml:person xmlns:personxml="http://www.your.example.com/xml/person" xmlns:cityxml="http://www.my.example.com/xml/cities">
<personxml:name>Rob</personxml:name>
<personxml:age>37</personxml:age>
<cityxml:homecity>
<cityxml:name>London</cityxml:name>
<cityxml:lat>123.000</cityxml:lat>
<cityxml:long>0.00</cityxml:long>
</cityxml:homecity>
Now i want to get value of tag <cityxml:lat> as 123.00
Code :
string xml = "<personxml:person xmlns:personxml='http://www.your.example.com/xml/person' xmlns:cityxml='http://www.my.example.com/xml/cities'><personxml:name>Rob</personxml:name><personxml:age>37</personxml:age><cityxml:homecity><cityxml:name>London</cityxml:name><cityxml:lat>123.000</cityxml:lat><cityxml:long>0.00</cityxml:long></cityxml:homecity></personxml:person>";
var elem = XElement.Parse(xml);
var value = elem.Element("OTA_personxml/cityxml:homecity").Value;
Error i am getting
The '/' character, hexadecimal value 0x2F, cannot be included in a name.
You need to use XNamespace. For example:
XNamespace ns1 = "http://www.your.example.com/xml/person";
XNamespace ns2 = "http://www.my.example.com/xml/cities";
var elem = XElement.Parse(xml);
var value = elem.Element(ns2 + "homecity").Element(ns2 + "name").Value;
//value = "London"
Create XNamespace using a string that contains the URI, then combine the namespace with the local name.
For more information, see here.
You are better off using a XmlDocument to navigate your xml.
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
XmlNode node = doc.SelectSingleNode("//cityxml:homecity/cityxml:lat");
string latvalue = null;
if (node != null) latvalue = node.InnerText;
The error I got with your code was that there needs to be a namespace to parse the XML properly
Try :
XNamespace ns1 = "http://www.your.example.com/xml/cities";
string value = elem.Element(ns1 + "homecity").Element(ns1 + "name").Value;
I would still advice using XDocuments to parse if possible, but the above is fine if your way is a must.

How to get value of element with XDocument and Linq to XML

I want to collect the RequestID element with the namespace, but I do not know how.
this.XmlString = "<?xml version=\"1.0\"
encoding=\"utf-8\"?><MethodNameRq xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><RequestID
xmlns=\"http://Mynamespace\">573-348976-428697-346</RequestID ></MethodNameRq>";
var doc = XDocument.Parse(this.XmlString);
this.RequestId = (string)doc.Descendants().Where(n => n.Name
== "RequestID ").FirstOrDefault();
This collects an empty string for RequestID. It does work if the string has no namespaces included. Does anyone know how I can collect the RequestID element?
you need to specify the namespace of your element
XNamespace ns = "http://Mynamespace";
this.RequestId = (string)doc.Descendants(ns + "RequestID").FirstOrDefault();

Categories