LINQ 4 XML - What is the proper way to query deep in the tree structure?


LINQ 4 XML - What is the proper way to query deep in the tree structure?



I have an XML structure that is 4 deep:

<?xml version="1.0" encoding="utf-8"?> <EmailRuleList xmlns:xsd="EmailRules.xsd">   <TargetPST name="Tech Communities">     <Parse emailAsList="true" useJustDomain="false" fromAddress="false" toAddress="true">       <EmailRule address="@aspadvice.com" folder="Lists, ASP" saveAttachments="false" />       <EmailRule address="@sqladvice.com" folder="Lists, SQL" saveAttachments="false" />       <EmailRule address="@xmladvice.com" folder="Lists, XML" saveAttachments="false" />     </Parse>     <Parse emailAsList="false" useJustDomain="false" fromAddress="false" toAddress="true">       <EmailRule address="northcoloradoarchitects@googlegroups.com" folder="Special Interest Groups|Northern Colorado Architects Group" saveAttachments="false" />       <EmailRule address="spambayes@python.org" folder="Support|SpamBayes" saveAttachments="false" />     </Parse>     <Parse emailAsList="false" useJustDomain="false" fromAddress="true" toAddress="false">       <EmailRule address="support@godaddy.com" folder="Support|GoDaddy" saveAttachments="false" />       <EmailRule address="renew@no-ip.com" folder="Support|No-IP.com" saveAttachments="false" />       <EmailRule address="discuss@orchardproject.net" folder="Discussions|Orchard Project" saveAttachments="false" />     </Parse>     <Parse emailAsList="false" useJustDomain="true" fromAddress="true" toAddress="false">       <EmailRule address="@agilejournal.com"     folder="Newsletters|Agile Journal" saveAttachments="false"/>       <EmailRule address="@axosoft.ccsend.com"   folder="Newsletters|Axosoft Newsletter" saveAttachments="false"/>       <EmailRule address="@axosoft.com"          folder="Newsletters|Axosoft Newsletter" saveAttachments="false"/>       <EmailRule address="@cmcrossroads.com"     folder="Newsletters|CM Crossroads" saveAttachments="false" />       <EmailRule address="@urbancode.com"        folder="Newsletters|Urbancode" saveAttachments="false" />       <EmailRule address="@urbancode.ccsend.com" folder="Newsletters|Urbancode" saveAttachments="false" />       <EmailRule address="@Infragistics.com"     folder="Newsletters|Infragistics" saveAttachments="false" />       <EmailRule address="@zdnet.online.com"     folder="Newsletters|ZDNet Tech Update Today" saveAttachments="false" />       <EmailRule address="@sqlservercentral.com" folder="Newsletters|SQLServerCentral.com" saveAttachments="false" />       <EmailRule address="@simple-talk.com"      folder="Newsletters|Simple-Talk Newsletter" saveAttachments="false" />     </Parse>   </TargetPST>   <TargetPST name="[Sharpen the Saw]">     <Parse emailAsList="false" useJustDomain="false" fromAddress="false" toAddress="true">       <EmailRule address="rmiug-jobs@yahoogroups.com" folder="Head Geek|Job Alerts" saveAttachments="false" />       <EmailRule address="inkedinusmc@yahoogroups.com" folder="Social|LinkedIn USMC" saveAttachments="false"/>     </Parse>     <Parse emailAsList="false" useJustDomain="false" fromAddress="true" toAddress="false">       <EmailRule address="JobAlerts@CyberCoders.com" folder="Head Geek|Job Alerts" saveAttachments="false" />       <EmailRule address="jobs@dice.com" folder="Head Geek|Job Alerts" saveAttachments="false" />       <EmailRule address="news@cruisecritic.com" folder="Social|Cruise Critic" saveAttachments="false"/>     </Parse>     <Parse emailAsList="false" useJustDomain="true" fromAddress="true" toAddress="false">       <EmailRule address="@moody.edu" folder="Social|5 Love Languages" saveAttachments="false" />       <EmailRule address="@postmaster.twitter.com" folder="Social|Twitter" saveAttachments="false"/>       <EmailRule address="@diabetes.org" folder="Physical|American Diabetes Association" saveAttachments="false"/>       <EmailRule address="@membership.webshots.com" folder="Social|Webshots" saveAttachments="false"/>     </Parse>   </TargetPST> </EmailRuleList> 

Now, I have both an FromAddress and a ToAddress that is parsed from an incoming email. I would like to do a LINQ query against a class set that was deserialized from this XML. For instance: ToAddress = asp@aspadvice.com FromAddress = keithb@sol3.net

Query:

  • Get EmailRule.Include(Parse).Include(TargetPST) where address == ToAddress AND Parse.ToAddress==true AND Parse.useJustDomain==false
  • Get EmailRule.Include(Parse).Include(TargetPST) where address == [ToAddress Domain Only] AND Parse.ToAddress==true AND Parse.useJustDomain==true
  • Get EmailRule.Include(Parse).Include(TargetPST) where address == FromAddress AND Parse.FromAddress==true AND Parse.useJustDomain==false
  • Get EmailRule.Include(Parse).Include(TargetPST) where address == [FromAddress Domain Only] AND Parse.FromAddress==true AND Parse.useJustDomain==true

I am having a hard time figuring this LINQ query out. I can, of course, loop on all the bits in the XML like so (includes deserialization into objects):

XmlSerializer s = new XmlSerializer(typeof(EmailRuleList)); TextReader r = new StreamReader(path); _emailRuleList = (EmailRuleList)s.Deserialize(r);  TargetPST[] PSTList = _emailRuleList.Items; foreach (TargetPST targetPST in PSTList) {     olRoot = GetRootFolder(targetPST.name);     if (olRoot != null)     {         Parse[] ParseList = targetPST.Items;         foreach (Parse parseRules in ParseList)         {             EmailRule[] EmailRuleList = parseRules.Items;             foreach (EmailRule targetFolders in EmailRuleList)             {             }         }     } } 

However, this means going through all these loops for each and every address. It makes more sense to me to query against the Objects. Any tips appreciated!




Change an editable-text value in Allegro CL

1:



Why is consing in Lisp slow?
This code you have here:.
Lexical closures over macrolet?
XmlSerializer s = new XmlSerializer(typeof(EmailRuleList));  TextReader r = new StreamReader(path);  _emailRuleList = (EmailRuleList)s.Deserialize(r);   TargetPST[] PSTList = _emailRuleList.Items;  foreach (TargetPST targetPST in PSTList)  {      olRoot = GetRootFolder(targetPST.name);      if (olRoot != null)      {          Parse[] ParseList = targetPST.Items;          foreach (Parse parseRules in ParseList)          {              EmailRule[] EmailRuleList = parseRules.Items;              foreach (EmailRule targetFolders in EmailRuleList)              {              }          }      }  }  
Is effectively just the following in LINQ:.
How does Lisp let you redefine the language itself?
var query = from targetPST in _emailRuleList.Items             let olRoot = GetRootFolder(targetPST.name)             where olRoot != null             from parseList in targetPST.Items             from emailRule in parseList.Items             select [whatever you want to select]; 
From here, just include the appropriate where clauses.


What features is lisp lacking? [closed]
At every "level" you have access to the objects previously specified in a from clause, so if you wanted to do one of your queries (your first one), it'd be something like this:.
Lisp simple question
where emailRule.address == ToAddress &&      parseList.toAddress == true &&     parseList.useJustDomain == false select new {     EmailRule = emailRule,     Parse = parseList,     TargetPST = targetPST } 
To do this in methods, I think you're doing more harm than good (esp in readability), but here it is.


How to process input and output streams in Steel Bank Common Lisp?
The important thing to note on why this is so complicated is that a nested set of FROM clauses translates into a SelectMany, and because ultimately you need the EmailRule with its associated parent objects, you have to do all your selecting inside a set of nested lambdas in order to have references to the parent objects (since the child objects themselves do not have backreferences)..
The subsets-sum problem and the solvability of NP-complete problems
_emailRuleList     .Where( targetPst => GetRootFolder( targetPst.Name ) != null )     .SelectMany( targetPst => {         return targetPst.Items.SelectMany( parse => {             return parse.Items.Select( rule => {                 return new {                     TargetPST = targetPst,                     Parse = parse,                     EmailRule = rule                 };             } );         } );     } )     .Where( x => x.EmailRule.address == ToAddress &&                  x.Parse.toAddress == true &&                  x.Parse.useJustDomain == false ); 



92 out of 100 based on 82 user ratings 482 reviews