How can I grab all the child elements in XML? - c#

From this XML response: http://www.dreamincode.net/forums/xml.php?showuser=335389
I want to grab all of the users friends. I need to grab all of the information from the friends. Usually with the help I've been given I would use the unique ID to grab each, but since each users doesn't have the same friends it has to be dynamic and I can't hard code anything.
Would anyone please share some XDocument magic?

You can get all <user> elements in the <friends> element from the XML document like this:
var url = "http://www.dreamincode.net/forums/xml.php?showuser=335389";
var doc = XDocument.Load(url);
var friends = doc.Element("ipb").Element("profile")
.Element("friends").Elements("user");
// Or if you don't want to specify the whole path and you know that
// there is only a single element named <friends>:
var friends = doc.Descendant("friends").Elements("user");
Then you can use LINQ to process the collection. For example, to create a IEnumerable<string> with the names of all frineds, you could write:
var names = from fr in friends
select fr.Element("name").Value;
If you needed unique ID, you could read the <id> element in a similar way (if it is an integer, you could also parse it using Int32.Parse for example...)

you can probably use XPath query
http://www.w3schools.com/xpath/xpath_examples.asp
the examples uses JScript but it is also supported in .NET

Related

How to get the content of XML nodes that have little differences? (C#)

I want to parse different XML that all of them have the same content but with this differences:
Some of the XML are like:
<ds:X509Data><ds:X509Certificate>MIIDtT[...]lLgXlaoNwM=</ds:X509Certificate></ds:X509Data>
Others are:
<dsig:X509Data><dsig:X509Certificate>MIIDtT[...]lLgXlaoNwM=</dsig:X509Certificate></dsig:X509Data>
I want to get the content of the "X509Certificate" node to save it in a file.
For other parts of the XML that are always the same, I was using:
doc.GetElementsByTagName("CountryName");
But I cant do the same here.
What should I do?
You can use XDocument Class and query it with LINQ.
var certificates = from doc in xDoc.Root.documents()
from attr in doc.Attributes()
where attr.Name.ToString().Contains("X509Certificate")
select attr;
You can now loop through certificates and read in the values

Retrieve Values manually from XML InnerXML

I have been trying to deserialize the InnerXML into a class and for some reason the XML keeps changing shape and however many times I try to get the class right it seems to change shape again.
So I have given up and decided to try another method.
Is it possible to retrieve the value of a parameter within the InnerXML manually using c#?
Say for example, my XML innerXML looked like this:
<Timestamp>2014-08-22T21:45:00Z</Timestamp>
<Subscriber>https://www.dogdoza.co.uk</Subscriber>
<Order>
<OrderID>111867</OrderID>
<InvoiceNumber>DOZA-9725410</InvoiceNumber>
<CustomerID>4542</CustomerID>
Is it possible to pull out say the value of Subscriber
If this is possible I can just pull out the values I want manually. Not ideal, but there are only about 10...
I have looked around but not managed to find any code I can get working..
Can anyone please give me any guidance?
Thanks
You can do achieve what you want using LINQ to XML:
XElement myXml = XElement.Load(#"XmlLocationHere");
XElement subscriber = myXml.Descendants("Subscriber").FirstOrDefault();
XElement.Descendants returns a collection of the descendant elements for this document or element, in document order. This method will return an IEnumerable<XElement>, since there might be more than one "Subscriber" element, but in your case, we choose FirstOrDefault, which returns the first occurrence.
Try loading your XML into an XDocument. Then try to use XPathSelectElement to find the specific value you want.
It could be that you need to wrap your inner xml into a root element, because it doesn't accept multiple roots.
Pseudo example:
// set up your xml document
string xml = "<rootelement>" + myInnerXml + "</rootelement>";
XDocument doc = new XDocument();
doc.Parse(xml);
XElement subscriber = doc.XPathSelectElement("/rootelement/Subscriber");
string value = subscriber.Value;

C# Load Datatable from LinQ XDocument using Using XPath where Xpath not known at compile time

I have a LinQ XDocument (from a SOAP response) that I want to turn into a Datatable. Here is the XML I am dealig with. It uses namespaces to further complicate the matter.
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:getDetailsResponse xmlns:ns2="http://service.xyz.com/">
<return>
<meeting meetingCode="8">
<meetingDate>2013-07-08T00:00:00+10:00</meetingDate>
<actionList>
<actionCoOrdinator>The action man</actionCoOrdinator>
<action>
<actionType>Type1</actionType>
<actionBy>John</actionBy>
</action>
<action>
<actionType>Type2</actionType>
<actionBy>Mary</actionBy>
</action>
<action>
<actionType>Type3</actionType>
<actionBy>Phil</actionBy>
</action>
</actionList>
</meeting>
</return>
</ns2:getDetailsResponse>
</soap:Body>
</soap:Envelope>
And here is the output that want in a DataTable
MeetingCode MeetingDate ActionCoOrdinator ActionType ActionBy
----------- ------------------------- ----------------- ---------- --------
8 2013-07-08T00:00:00+10:00 The action man Type1 John
8 2013-07-08T00:00:00+10:00 The action man Type2 Mary
8 2013-07-08T00:00:00+10:00 The action man Type3 Phil
As you can see I want a row for each "action" element within "actionList" but for each row I also need some info from parent/grandparent elements. All I have at this this stage is an XDocument using the code below;
XDocument myXDoc = XDocument.Parse(soapStringResult);
I've seen various posts about extracting data from an XDocument on this site but my problem is that the data items i want are not know beforehand. My starting point is an xPath which represents the "rows". The Xpath is
ns2:getDetailsResponse/return/meeting/actionList/action
Then i have a DB table that contains all the data items i want relative to this Xpath. The table looks like this
XpathDataItem
---------------------
../../#meetingCode
../../meetingDate
../actionCoOrdinator
actionType
actionBy
I can load the data into a DataTable when I know the Xpaths of the data items I'm looking for but I just dont know how to do it with an unknown set of XPaths's.
Thanks in advance
John
Which part is unknown? The starting point or the individual elements to retrieve? That's not clear from your question. If you simply don't know the starting point, then Linq-to-xml will work great for this.
Linq-to-xml doesn't normally retrieve elements based on xpath. The Elements() and Descendants() methods allow you query the xml data without knowing the specific path.
To retrieve the meetingDate regardless of what its path is, you could use the Descendants() method like this:
var meetingDateElement = myXDoc.Descendants("meetingDate").SingleOrDefault;
if (meetingDateElement != null) {
var meetingDate = meetingDateElement.Value;
}
meetingCode and actionCoOrdinator could be found in a similar manner.
And to get all the action elements, you'd simple use myXDoc.Descendants("action"). Something like this would get you the values for each action:
var actions = from a in myXDoc.Descendants("action")
select new {
actionType = a.Element("actionType").Value,
actionBy = a.Element("actionBy").Value
};
If the xml you're parsing could contain more than one meeting element, then you'd use `myXDoc.Descendants("meeting") to get all the meetings and retrieve child elements within a query or foreach statement.

XML Sorting options C# .Net

I am trying to print out documents in various different orders. Right now I have a collection of print objects and an XML document where each node has attributes associated with a print object in the collection. I want to sort these objects by sorting the XML document based on these attributes.
Right now I am using a series of collections that i am cycling through and adding the node into a new collection based on the sorting i need done. The problem is 3 or 4 sorts in it gets messy. I am sure there has to be a better way to sort this collection of print objects, using XML or not.
Here are some attributes that my XML has that i am sorting on:
# of pages
Zip Code listed on document
Name of Document
Does anyone have a better idea?
thanks,
EDIT -
my document will look something like
<xml>
<claim key="1" att1="wd" att2="de"/>
<claim key="2" att1="wd" att2="de"/>
<claim key="3" att1="wd" att2="de"/>
<claim key="4" att1="wd" att2="de"/>
</xml>
The key value is associated with a spot in the print object collection. The claim nodes may have more child nodes but i do not think that is relevant at this point. I would just like to be able to sort based on the attributes, there will be at least 3 attributes but more may be added. Also this needs to be versatile so if I need to switch the sorting order it should be somewhat easy to rearrange. Once I have the XML in the correct order I want, then i use a cycle through the XML in order putting the key into a list and then print out the Print objects by the keys in that list.
thanks,
I tried this example out in LINQPad and it seems to do what you're asking.
var root = XDocument.Parse("<xml><claim>...</claim></xml>").Element("xml");
var query = from claim in root.Elements("claim")
let key = claim.Attributes("key").First().Value
let att1 = claim.Attributes("att1").First().Value
let att2 = claim.Attributes("att2").First().Value
orderby key, att1, att2
select claim;
It finds the <claim> nodes in your XML, selects the attributes on which you'd like to sort, sorts them, and then returns an IEnumerable<XElement> collection representing the sorted <claim> nodes.
You can then use the query result to build your Print objects, or you could change the above to have it do it for you:
var query2 = from claim in root.Elements("claim")
let key = claim.Attributes("key").First().Value
let att1 = claim.Attributes("att1").First().Value
let att2 = claim.Attributes("att2").First().Value
orderby key, att1, att2
select new Print {
Property1 = key, // do type conversion if needed
Property2 = att1,
Property3 = att2
};
I think it fits the maintainability requirements you mentioned -- you just have to change add/remove/change the attribute names in the LINQ query if you need to sort differently.
EDIT: To get the key into a list of ints, as per your comment below:
var printKeys = (from claim in query
select Integer.Parse(claim.Attributes("key").First().Value)).ToList();

How to get the immediate child elements of the root element using C# and XML?

<Document>
<Heading1>
<text>Heading Title</text>
<para>para1</para>
<para>para2</para>
<para>para3</para>
</Heading1>
<Heading1>
<text>2nd Heading Title</text>
<para>para4</para>
<para>para5</para>
<para>para6</para>
<Heading2>
<text>3rd Heading Title</text>
<para>para4</para>
<para>para5</para>
</Heading2>
</Heading1>
</Document>
This is XML Document. Now, i want to parse this XML file using C# (4.0). Here, I want to get all the Heading1 elements without using that element name in my program. For example, don't use document.GetElementsByTagName("Heading1");. How i get it. Guide me get out of this issue.
Thanks & Regards.
Using LINQ to XML, you can do:
var headings = yourXDocument.Root.Elements();
Using Nodes() instead of Elements() will also return text nodes and comments, which is apparently not what you want.
You can access the child elements of the document or element through the Elements() method if using LINQ to XML.
XDocument doc = ...;
var query = doc.Root.Elements();
If you're using XmlDocument, this works:
var elements = doc.SelectNodes("/*/*");
That finds all child elements of the top-level element irrespective of any of their names. It's usually safer to specify the names if you know them, so that elements with unexpected names don't get returned in your list - use /Document/Heading1 to do this.

Categories

Resources