XML Sorting options C# .Net - c#

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();

Related

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;

Sort XmlNodeList with a specific Node value

I searched the web for this, but I am not able to find any related solution.
I have following XML
<Table>
<Entity>Employee</Entity>
<EntityID>2786</EntityID>
<Goal>
<GoalId>31931</GoalId>
<FilterData>LastModifiedOn¥2014-03-20T18:11:01.0000000+05:30ÆActiveTaskCount¥0</FilterData>
</Goal>
<Goal>
<GoalId>31932</GoalId>
<FilterData>LastModifiedOn¥2014-03-22T15:26:09.0000000+05:30ÆActiveTaskCount¥0</FilterData>
</Goal>
<Goal>
<GoalId>31932</GoalId>
<FilterData>LastModifiedOn¥2014-03-22T09:25:00.0000000+05:30ÆActiveTaskCount¥0</FilterData>
</Goal>
</Table>
From above XML when I read the data I got 2 separate DataTables; 1 for Employees and another one for related Goals.
What I needed is I want to sort all the Goals related to an employee with respect to LastModifiedOn from FilterData node.
NOTE: I am getting the LastModifiedOn value by split node value like this
nodevalue.Split('Æ')[0].Split('¥')[1]
Right now I am using System.XML namespace for doing operations. I also looked at LINQ TO XML but I am unable to make it work.
I am getting the XMLNodelist by following code
XmlNodeList GoalNodesList = doc.DocumentElement.SelectNodes("/NewDataSet/Table[Entity='Employee' and EntityID='" + EntityId + "']/Goal");
Here I want the Sorted Goals (with respect to LastModifiedOn).
I also looked at some useful links but didn't get any idea so far
Sorting XML nodes based on DateTime attribute C#, XPath
XMLdocument Sort
I am ready to convert the code into LINQ TO XML but needed a brief example.
One thing you could try is creating a collection of key value pairs where key is the goal and value is the date. You could then override the CompareTo method by comparing the dates and then you could just use [collection name].Sort(). Hope this helps

Get specific data from XML document

I have xml document like this:
<level1>
<level2>
<level3>
<attribute1>...</attribute1>
<attribute2>false</attribute2>
<attribute3>...</attribute3>
</level3>
<level3>
<attribute1>...</attribute1>
<attribute2>true</attribute2>
<attribute3>...</attribute3>
</level3>
</level2>
<level2>
<level3>
<attribute1>...</attribute1>
<attribute2>false</attribute2>
...
...
...
I'm using c#, and I want to go thru all "level3", and for every "level3", i want to read attribute2, and if it says "true", i want to print the corresponding attribute3 (can be "level3" without these attributes).
I keep the xml in XmlDocument.
Then I keep all the "level3" nodes like this:
XmlNodeList xnList = document.SelectNodes(String.Format("/level1/level2/level3"));
(document is the XmlDocument).
But from now on, I don't know exactly how to continue. I tried going thru xnList with for..each, but nothing works fine for me..
How can I do it?
Thanks a lot
Well I'd use LINQ to XML:
var results = from level3 in doc.Descendants("level3")
where (bool) level3.Element("attribute2")
select level3.Element("attribute3").Value;
foreach (string result in results)
{
Console.WriteLine(result);
}
LINQ to XML makes all kinds of things much simpler than the XmlDocument API. Of course, the downside is that it requires .NET 3.5...
(By the way, naming elements attributeN is a bit confusing... one would expect attribute to refer to an actual XML attribute...)
You can use LINQ to XML and reading this is a good start.
You can use an XPath query. This will give you a XmlNodeList that contains all <attribute3> elements that match your requirement:
var list = document.SelectNodes("//level3[attribute2 = 'true']/attribute3");
foreach(XmlNode node in list)
{
Console.WriteLine(node.InnerText);
}
You can split the above xpath query in three parts:
"//level3" queries for all descendant elements named <level3>.
"[attribute2 = 'true']" filters the result from (1) and only keeps the elements where the child element <attribute2> contains the text true.
"/attribute3" takes the <attribute3> childnode of each element in the result of (2).

How can I grab all the child elements in XML?

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

how to load a hashtable from a simple xml file using xmltextreader

using xmltextreader, how would I load a hashtable.
XML:
<base><user name="john">2342343</user><user name="mark">239099393</user></base>
This was asked before but it was using some funky linq that I am not fully comfortable with just yet.
Well, the LINQ to XML solution is really easy, so I suggest we try to make you comfortable with that instead of creating a more complex solution. Here's the code, with plenty of explanation...
// Load the whole document into memory, as an element
XElement root = XElement.Load(xmlReader);
// Get a sequence of users
IEnumerable<XElement> users = root.Elements("user");
// Convert this sequence to a dictionary...
Dictionary<string, string> userMap = users.ToDictionary(
element => element.Attribute("name").Value, // Key selector
element => element.Value); // Value selector
Of course you could do this all in one go - and I'd probably combine the second and third statements. But that's about as conceptually simple as it's likely to get. It would become more complicated if you wanted to put error handling around the possibility that a user element might not have a name, admittedly. (This code will throw a NullReferenceException in that case.)
Note that this assumes you want the name as the key and id as value. If you want the hashtable the other way round, just switch the order of the lambda expressions.

Categories

Resources