I have a Xml document that I want to convert into a XnlNodeList using a linq query. Now, neither Xml nor Linq are something know well. The error I'm getting is Cannot implicitly convert type 'System.Linq.IOrderedEnumerable<System.Xml.XmlElement>' to 'System.Xml.XmlNodeList'. An explicit conversion exists (are you missing a cast?).
XmlNodeList abTestDocx = abTestDoc.GetElementsByTagName("FS").OfType<XmlElement>().OrderBy(FS => FS.GetAttribute("label"));
Thanks!
You don't generally create XmlNodeList instances yourself. Do you really need one though? If you just need to iterate over the nodes, just assign it to an IEnumerable<XmlElement>:
IEnumerable<XmlElement> abTestDocx = abTestDoc
.GetElementsByTagName("FS")
.OfType<XmlElement>()
.OrderBy(fs => fs.GetAttribute("label"));
Note that using LINQ to XML is generally nicer than the old XmlDocument API. Then you'd just need:
IEnumerable<XElement> abTestDocx = doc
.Descendants("FS")
.OrderBy(fs => (string) fs.Attribute("label"));
... and all kinds of other things would be simpler too. LINQ to XML is lovely :)
Related
I've been playing with LINQ in VB.Net and some other things in an attempt to delete XML nodes based on attribute values. Basically, if any node in my XML documents has an attribute of a particular value, "cats" for example, I want to delete it.
The catch is I won't really know exactly what the XML structures will look like, so I can't give a path. Also, I know some of the attributes that may contain "cats", but I don't want to hard code them if possible.
So, in other words, I don't have a set XML structure, and I want to delete ANY node that has "cats" as an attribute value, like Caption = "cats" or Title = "cats", anywhere in the node. If it has "cats", nuke it.
Is this at all possible? Or do I just need to give up on this project?
BTW, I'm trying to write the solution in VB.Net, but I am quite capable of reading and converting C# if someone happens to know how to accomplish this but can only give C# code.
Thanks a ton for any help!
You can do this using:
XDocument.Descendants() to iterate through all elements in your document.
XElement.Attributes() to loop through all attributes of an element, to see if any have a value of "cats".
Extensions.Remove() to remove all elements that have an attribute value that matches.
In c# this becomes:
var doc = XDocument.Parse(xmlString);
var attributeValue = "cats";
doc.Descendants().Where(e => e.Attributes().Any(a => (string)a == attributeValue)).Remove();
And in VB.NET:
Dim doc = XDocument.Parse(xmlString)
Dim attributeValue = "cats"
doc.Descendants().Where(Function(e) e.Attributes().Any(Function(a) CStr(a) = attributeValue)).Remove()
Example fiddle.
I have an XML document that i have deserialized according to my model class, now i want to convert it into an IEnumerable<XmlDocument> or IEnumerable<string> which is the return type of my function so i could return valid XML reply from my MVC REST API.
XmlDocument xml = new XmlDocument();
xml.LoadXml(responseStream);
XmlSerializer x = new XmlSerializer(typeof(mSchoolModel));
mSchoolModel mgp = (mSchoolModel)x.Deserialize(responseObj.GetResponseStream());
//return xml;
So can anyone help me how can i convert this into an IEnumerable?
Use the LINQ-to-XML API.
Convert your XmlDocument instance to an XDocument instance. Instructions available at: http://blogs.msdn.com/b/xmlteam/archive/2009/03/31/converting-from-xmldocument-to-xdocument.aspx
Use the Elements() or Descendants() methods on the XDocument instance to get an IEnumerable<XElement>
Transform the IEnumerable<XElement> to an IEnumerable<string> using the LINQ Enumerable.Select() operator.
Here's a simple example:
IEnumerable<string> elements
= XDocument
.Load(new XmlNodeReader(xml))
.Elements()
.Select(element => element.ToString());
*Note: since a valid XML document can only have one root node, the resulting collection from the example above won't be very interesting, but you should have enough here to get what it is that you need. If you're familiar with XPath, you may find it easier to get the elements you want using the XPath extensions to LINQ to XML. See: How To: Query LINQ to XML Using XPath
Update
Realized I may have read your question wrong. If you have an XmlDocument instance and you need to return an IEnumerable<XmlDocument> all you have to do is wrap the instance in a collection. For example,
IEnumerable<XmlDocument> xmlCollection = new XmlDocument[]{ xml };
Of course, this approach can be used for wrapping any object into a singleton collection of objects of the same type.
This is driving me a little crazy. I am pulling an XML string from a database column and successfully creating an XDocument using XDocument.Parse. I've used linq to xml before to query xml trees but for some reason on this everything I am doing is returning null. Is it something to do with the namespace?
Here is a sampling of the text visualizer for my XDocument object:
// removed XML for privacy reasons
An example of the query I am trying:
XElement algorithmId = (from algoId in reportLogXml.Descendants(ALGORITHM_ID)
select algoId).FirstOrDefault();
I am using a constant for the string value and I have quadruple checked that the spelling matches as well as trying several different elements that are clearly in the document but they all return null. What am I doing wrong here?
Yes, it probably has to do with the namespace but also the <AlgorithmId> element has no descendants.
You can fix the ns problem like this:
//untested
XNameSpace ns0 = "http://schemas.datacontract.org/2004/07/Adapters.Adapter";
var ns1 = reportLogXml.Root.GetDefaultNamespace();
// check: ns0 and ns1 should be equal here
... in reportLogXml.Descendants(ns1 + ALGORITHM_ID)
Note that this is a special + operator, follow the format exactly.
What is best way to search in XML document to retrieve one or more records against search criteria. Suggestions are welcomed.
Personally I'd use LINQ to XML if you possibly can. Your question is very vague at the moment, but for example, you could write:
XDocument doc = XDocument.Load("test.xml");
var matches = doc.Descendants("Person")
.Where(x => (string) x.Attribute("Name") == "Jon")
.Where(x => x.Elements("Child").Count() >= 2);
While you can use XPath, I generally prefer not to - it has all the normal problems of embedding one language within another, whereas using LINQ to XML you're using C# throughout, so you have no new syntax to learn - just the relevant methods within the LINQ to XML library.
LINQ to XML also makes namespace handling simple, and you don't need to worry about escaping values etc, as your query is all in code rather than in a string.
.net xml documents have good support for xpath.
It should work for most of your xml searches.
Take a look at XPath Examples
Use XPath by XmlDocument.SelectNodes or SelectSingleNode like this:
XmlDocument doc = new XmlDocument();
doc.Load("bookstore.xml");
XmlNode root = doc.DocumentElement;
// Add the namespace.
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("bk", "urn:newbooks-schema");
// Select and display the first node in which the author's
// last name is Kingsolver.
XmlNode node = root.SelectSingleNode(
"descendant::bk:book[bk:author/bk:last-name='Kingsolver']", nsmgr);
Console.WriteLine(node.InnerXml);
I am calling a sharepoint service /_vti_bin/usergroup.asmx from my silverlight app. In that the method GetAllUserCollectionFromWeb() returns the XML string. I need to iterate through that XML string to get the required data. But the LINQ to XML in this scenario is not working, as it is working when loading the XML file and getting the req data. How to do the similar functionality of LINQ to SQL with an XML string?
Sample code:
string str = #"<LanguageDetails>
<UserNode>
<Lang>
English
</Lang>
</UserNode>
</LanguageDetails>";
Need to handle the similar string and iterate to read the value using LINQ to XML.
You mean something like this?
string str = #"<LanguageDetails>
<UserNode>
<Lang>
English
</Lang>
</UserNode>
</LanguageDetails>";
XElement xLanguageDetails = XElement.Parse(str);
foreach (XElement xUserNode in xLanguageDetails.Elements("UserNode"))
{
}
In almost all cases where you return no rows when doing LINQ to XML queries, the reason is because there is a namespace in your XML. Check the root nodes to see if there are any namespaces and include them in your LINQ queries.