I have this list of object:

public List<XHTMLError> Report = new List<XHTMLError>();

Which is defined this way:

public class XHTMLError
{
       public List<string> Errors = new List<string>();
       private string _errorType;

     public string ErrorType { get { return _errorType; } set { _errorType = value; } }
        }

I am currently binding the collection to a repeater (used for an xml file) that contains another repeater (for the errors contained in the list of the XHTMLError object. It looks like this currently but the second repeater is not working, there must be some misunderstanding from my part of LINQ or ASP repeater.

<%@ Import Namespace="System.Linq" %>
<?xml version="1.0" encoding="utf-8" ?>
<ERRORS>
    <INFO Page_Affected="<%  %>" Total_Errors="<%  %>" />
        <asp:Repeater ID="types" runat="Server">
        <ItemTemplate>
            <ERROR type="<%# Eval("ErrorType") %>">
                <asp:Repeater id="pagelist" runat="Server" datasource="<%# Report.Where(p => p.ErrorType == Container.DataItem.ToString()).Select(result => result.Errors)  %>" >
                    <ItemTemplate>
                        <page id="<% %>" path="<% %>" />
                    </ItemTemplate>
                </asp:Repeater>
            </ERROR>
        </ItemTemplate>
    </asp:Repeater>
</ERRORS>

(The id is the element itself inside the collection Errors.

I wouldn't use a repeater to generate XML, but that's just me. If you want to continue down that path, I would advise you to explore the repeater's ItemDataBound event and take care of the binding of the second repeater within the code behind of the page.

As for another option, this will create an XDocument that you can then choose to save or otherwise render. XDocument is in the System.Xml.Linq namespace.

List<XHTMLError> errorCollection = new List<XHTMLError>();

        errorCollection.Add(new XHTMLError() { Errors = new List<string>() { "Apple", "Banana" }, ErrorType = "Big" });
        errorCollection.Add(new XHTMLError() { Errors = new List<string>() { "Cherry", "Orange" }, ErrorType = "Huge" });

        XDocument document = new XDocument(new XElement("ERRORS",
            new XElement("INFO",
                new XAttribute("Page_Affected", "something"),
                new XAttribute("Total_Errors", errorCollection.Count),
                from error in errorCollection
                select new XElement("ERROR",
                    new XAttribute("type", error.ErrorType),
                    from errorInfo in error.Errors
                    let index = error.Errors.IndexOf(errorInfo) 
                    select new XElement("page",
                        new XAttribute("id", index),
                        new XAttribute("path", errorInfo))))));


        document.Declaration = new XDeclaration("1.0", "utf-8", "yes");
        document.Save(@"C:\Temp\xmldemo.xml");

The final output looks like this

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<ERRORS>
  <INFO Page_Affected="something" Total_Errors="2">
    <ERROR type="Big">
      <page id="0" path="Apple" />
      <page id="1" path="Banana" />
    </ERROR>
    <ERROR type="Huge">
      <page id="0" path="Cherry" />
      <page id="1" path="Orange" />
    </ERROR>
  </INFO>
</ERRORS>

I wouldn't use a repeater to generate XML, but that's just me. If you want to continue down that path, I would advise you to explore the repeater's ItemDataBound event and take care of the binding of the second repeater within the code behind of the page.

As for another option, this will create an XDocument that you can then choose to save or otherwise render. XDocument is in the System.Xml.Linq namespace.

List<XHTMLError> errorCollection = new List<XHTMLError>();

        errorCollection.Add(new XHTMLError() { Errors = new List<string>() { "Apple", "Banana" }, ErrorType = "Big" });
        errorCollection.Add(new XHTMLError() { Errors = new List<string>() { "Cherry", "Orange" }, ErrorType = "Huge" });

        XDocument document = new XDocument(new XElement("ERRORS",
            new XElement("INFO",
                new XAttribute("Page_Affected", "something"),
                new XAttribute("Total_Errors", errorCollection.Count),
                from error in errorCollection
                select new XElement("ERROR",
                    new XAttribute("type", error.ErrorType),
                    from errorInfo in error.Errors
                    let index = error.Errors.IndexOf(errorInfo) 
                    select new XElement("page",
                        new XAttribute("id", index),
                        new XAttribute("path", errorInfo))))));


        document.Declaration = new XDeclaration("1.0", "utf-8", "yes");
        document.Save(@"C:\Temp\xmldemo.xml");

The final output looks like this

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<ERRORS>
  <INFO Page_Affected="something" Total_Errors="2">
    <ERROR type="Big">
      <page id="0" path="Apple" />
      <page id="1" path="Banana" />
    </ERROR>
    <ERROR type="Huge">
      <page id="0" path="Cherry" />
      <page id="1" path="Orange" />
    </ERROR>
  </INFO>
</ERRORS>

I feel kinda bad that I didn't think about this easier solution, I got a little to obssessed with the repeater I guess hehe.

Thank you for your solution, however, I'd like to if there is way to make this easier to Read for code maintenance.

Something that looks like the XmlDocument method, let's say, something "less" inline. :)

xmlWriter.WriteStartElement("ERROR");
xmlWriter.WriteAttributeString("id", index);
xmlWriter.WriteAttributeString("path", path);
xmlWriter.WriteEndElement();

You can certainly construct the XML yourself and you can even construct an XDocument manually without the LINQ part by first creating the document, then adding XElements, add XAttributes and XElements inside those, etc., and build a loop. All LINQ is doing for you is abstracting that loop away, but it's still there behind the scenes. If it helps you read and understand and maintain it by doing it yourself, absolutely do it. I think you'll grow more comfortable with a LINQ approach eventually, though.

I think you'll grow more comfortable with a LINQ approach eventually, though.

Absolutely, I've been working quite a lot with LINQ in the last days and its potential is really awesome. I'm looking forward to buy a LINQ book soon.

Thank you for your help. I'll try to make sure of what's going on in that crazy query you gave me :).

This question has already been answered. Start a new discussion instead.