0

I have a very similar question to: LINQ to read XML

I need to go through an xml structure that has many child elements. The code in the link above I believe only uses the first two child elements. How can I go several levels deep in the structure, and execute a code snippet?

This is the code I'm trying to execute for each element, which is needed to create sharepoint sites:

SPWeb mySite = SPContext.Current.Web;
SPWebCollection subSites = mySite.Webs;
string currentTemplate = mySite.WebTemplate;

string siteUrl = TextBox1.Text.ToString();
string siteTitle = TextBox2.Text.ToString();
string siteDescription = TextBox3.Text.ToString();

subSites.Add(siteUrl, siteTitle, siteDescription, 1033, 
   currentTemplate, true, false); 
Community
  • 1
  • 1
MVZ
  • 2,220
  • 5
  • 27
  • 57
  • 1
    the [`Descendants(XName)`](http://msdn.microsoft.com/en-us/library/system.xml.linq.xdocument.descendants.aspx) method will return descendants from all levels of nesting when called on the root element. It's not clear from your question what the connection between the XML and your code is...? – Adam Dec 29 '11 at 17:11
  • 1
    It would help to see a sample of the XML and how it maps to the piece of code you want to execute. – Chris Taylor Dec 29 '11 at 17:12
  • Do you need to execute the snippet at each level or do you need to only execute the snippet for a certain level? For example, you have level1, level2, level3, and level4, are you only looking to execute at level4 or 1 through 4? – Josh Dec 29 '11 at 17:15
  • @Josh I need to execute the snippet at each level. The snippet I posted creates sites in SharePoint, so it would need to be executed at each level to create sites and subsites. – MVZ Dec 29 '11 at 17:19
  • @codesparkle The XML has a structure of sites and subsites. The code will create Sites in a SharePoint sever. – MVZ Dec 29 '11 at 17:20
  • Does the 2nd answer on the question you linked to give you what you need? http://stackoverflow.com/a/671692/69527 – CoderDennis Dec 29 '11 at 17:21
  • @ChrisTaylor the XML is very similar to: http://stackoverflow.com/questions/670563/linq-to-read-xml but with many more levels (over 8) – MVZ Dec 29 '11 at 17:21

1 Answers1

0

Here's a recursive solution, the x List in the RecurseElements method is just there so you can see what Descendants look like compared to querying for them. You'll also need to adjust it to query whatever you need. I'm just pulling from a name attribute. Also, if you want to enforce a max depth of recursion, just add that to the if statement at the top:

using System.Linq;
using System.Xml.Linq;
using System.Collections.Generic;

  private void RecurseElements(IEnumerable<XElement> descendants, int level)
  {
     if (descendants == null || !descendants.Any()) return;

     foreach (var d in descendants)
     {
        string levelName = d.Attribute("name").Value;
        System.Diagnostics.Debug.Print(string.Format("Level name {0}", levelName));
        var x = d.Descendants().ToList();
        var descendantElms = d.Descendants(string.Format("level{0}", level+1)).ToList();
        RecurseElements(descendantElms, level+1);
     }
  }

Call above with something similar to:

     XElement config = XElement.Parse(
         @"<root>
             <level1 name=""level1A"">
                 <level2 name=""level2A"">
                     <level3 name=""level3A"">
                         <level4 name=""level4A"">
                             <level5 name=""level5A"">
                                 <level6 name=""level6A"">
                                     <level7 name=""level7A"">
                                         <level8 name=""level8A""></level8>
                                     </level7>
                                 </level6>
                             </level5>
                         </level4>
                     </level3>
                 </level2>
             </level1>
             <level1 name=""level1B"">
                 <level2 name=""level2B"">
                     <level3 name=""level3B"">
                         <level4 name=""level4B"">
                             <level5 name=""level5B"">
                                 <level6 name=""level6B"">
                                     <level7 name=""level7B"">
                                         <level8 name=""level8B""></level8>
                                     </level7>
                                 </level6>
                             </level5>
                         </level4>
                     </level3>
                 </level2>
             </level1>
         </root>"
     );

     var descendants = config.Descendants("level1").ToList();
     RecurseElements(descendants, 1);

Your debug output should look like this:

Level name level1A
Level name level2A
Level name level3A
Level name level4A
Level name level5A
Level name level6A
Level name level7A
Level name level8A
Level name level1B
Level name level2B
Level name level3B
Level name level4B
Level name level5B
Level name level6B
Level name level7B
Level name level8B
Josh
  • 2,955
  • 1
  • 19
  • 28
  • Hi I'm trying your code, and it's telling me "the non genetic type System.Collections.IEnumerable cannot be used with type arguements... I think this is the answer I been looking for – MVZ Dec 29 '11 at 18:07
  • I added the using statements to the answer. Sounds like you're missing System.Collections.Generic. – Josh Dec 29 '11 at 18:10
  • nevermind I fixed it by adding: using System.Collections.Generic; I'l text your code and I'll get back to you – MVZ Dec 29 '11 at 18:10
  • How do I add the second part that has the xml structure in it? would you mind posting the whole code in one piece? Thanks for helping me out. – MVZ Dec 29 '11 at 18:32
  • You can just put that in a Load method or something. I made it from a quick project. Just put it wherever you need it to kick-off the processing. – Josh Dec 29 '11 at 18:38
  • So a "XDocument xdoc = XDocument.Load("file.xml");" should be enough? – MVZ Dec 29 '11 at 19:02
  • You would want to read the file into a StreamReader, then use XElement config = XElement.Parse(reader.ReadToEnd()) instead of hardcoding it like I did. – Josh Dec 29 '11 at 19:26