reading an XML string using LINQ - c#

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.

Related

Querying CIM XML in C# with LINQ

I am looking for a way to query CIM XML files with LINQ, in order to speed up my analysis of data and verify the exports from a database containing the elements of electrical network.
Since I am a newbie in C#, I guessed that it will be easy to load the CIM XML in console application and based on tag values filter some elements. However, all tutorials that I found so far are straight-forward where elements are named like "Student", "Purchase", etc.
My elements are named like "cim:LoadBreakSwitch", where "cim" is actual address defined in root node.
This way, when I try to select all elements named like "cim:LoadBreakSwitch", I get an exception thrown on Run Time because the name of a element cannot contain colon.
Example of element that I want to select from the CIM XML file:
<cim:LoadBreak rdf:ID="101">
<cim:ConductingEquipment.phases>A</cim:ConductingEquipment.phases>
<cim:IdentifiedObject.description>PoleMounted</cim:IdentifiedObject.description>
</cim:LoadBreak>
When I print in the console the names of all elements with
IEnumerable<XElement> elements = xmlDoc.Elements();
foreach (var item in elements)
{
Console.WriteLine(item.Name);
}
I get something like
"{http://[address from the root node]}LoadBreak".
I don't know if there is possibility to do it, but I am just curious did anyone who is experienced developer had need to do something similar.
Your XML is missing a root element with namespace declarations.
Here is a conceptual example for you. It shows how to handle namespaces and query XML with them.
c#
void Main()
{
XDocument xdoc = XDocument.Parse(#"<rdf:RDF xmlns:cim='http://iec.ch/TC57/2008/CIM-schema-cim13#'
xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'>
<cim:LoadBreak rdf:ID='101'>
<cim:ConductingEquipment.phases>A</cim:ConductingEquipment.phases>
<cim:IdentifiedObject.description>PoleMounted</cim:IdentifiedObject.description>
</cim:LoadBreak>
</rdf:RDF>");
XNamespace cim = xdoc.Root.GetNamespaceOfPrefix("cim");
XNamespace rdf = xdoc.Root.GetNamespaceOfPrefix("rdf");
foreach (XElement xelem in xdoc.Descendants(cim + "LoadBreak").Elements())
{
Console.WriteLine("{0}: {1}"
, xelem.Name.LocalName
, xelem.Value);
}
}
Output
ConductingEquipment.phases: A
IdentifiedObject.description: PoleMounted

Converting XML document into an IEnumerable

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.

How to filter Xdocument and return Xdocument?

My application gets data from SharePoint web service (using SOAP and CAML query), I am using a Xdocument doc to store retrieved xmlNode and then assign xdocument to XMLDataSource which is binned to gridView.
Now I need to filter the Xdocument before binding, to pick only those records where an element (ows_Partner_x0020_Type) matches a variable.
I am trying like this :
doc = doc.Descendants(z + "row").Where(rows => rows.Attribute("ows_Partner_x0020_Type").Value == Partner_Type.SelectedValue);
or
var bar = doc.Descendants(z + "row").Where(rows => rows.Attribute("ows_Partner_x0020_Type").Value == Partner_Type.SelectedValue);
but the problem is that return type of above LINQ is System.Collections.Generic.IEnumerable<System.Xml.Linq.XElement>
which is quit nothing like XDocument, which is required format to bind to XMLDataSource as doc.ToString().
Hope I am able to explain the problem.
Thanks a lot in advance.
Vishal
If you're just trying to create a document with those elements, you can use:
XDocument filteredDocument = new XDocument(new XElement("root", bar));
(That will create a document with a root element of <root>, and all the elements you're interested in directly under that.)
Not quite sure about all the binding parts - I strongly suspect there may be a better alternative - but this will certainly give you a new XDocument.

issue selecting descendants in LINQ to XML

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.

Using Linq to XML (C#) how do I find attribute values?

I have a simple XML file that looks something like:
<Institutions>
<FI name = "NameOne">
<longname>some text</longname>
<APIKey>some text</APIKey>
<connectstring>some text</connectstring>
</FI>
<FI name = "NameTwo">
<longname>some text</longname>
<APIKey>some text</APIKey>
<connectstring>some text </connectstring>
</FI>
</Institutions>
Using LINQ to XML I can grab the entire file, find all values for "longname", "APIKey" and "connectstring" but I can not figure out how to find all the "name" values or how to grab only the three pieces of information underneath each FI name value. Just to be clear, I will have NO IDEA what the name= values are in advance.
I'm using:
XElement root = XElement.Load("c:\\directory\\Data_Config.xml");
and
IEnumerable<XElement> Fis =
from el in root.Elements("Institutions")
select el;
to load the file, as per the MSDN documentation. All of it's references seem to imply knowledge of what the name value is that I would be querying.
I've googled, tried different Attribute/Element queries, all with no luck. I'm pretty sure it's something simple but it's evading me.
How do I get this data?
Thanks,
Jason
var xml = XElement.Load (#"c:\directory\Data_Config.xml");
var query =
from e in xml.Descendants("FI")
select e.Attribute("name").Value;

Categories