none
LINQ to XML - Element index? RRS feed

  • Question

  • Hi guys and gals,

    I have an XElement that contains the definition of a manual, containing sections and content items like so:

    <manual>
    <header>
    <!-- stuff here -->
    </header>
    <sections>
    <section>
    <header>
    <!-- stuff here -->
    </header>
    <contentItem>
    <!-- stuff here -->
    </contentItem>
    <contentItem>
    <!-- stuff here -->
    </contentItem>
    <contentItem>
    <!-- stuff here -->
    </contentItem>
    </section>
    <section>
    <header>
    <!-- stuff here -->
    </header>
    <contentItem>
    <!-- stuff here -->
    </contentItem>
    <contentItem>
    <!-- stuff here -->
    </contentItem>
    </section>
    </sections>
    </manual>

    I am querying the XElement usingLINQ to generate a table of contents for navigating the document:

    1   Dim content As XElement = tempManual.ManualContent
    2 ' Create navigation.
    3 Dim xNav As XElement = <Tree>
    4 <%= From section In content.<sections>.<section> _
    5 Select <Node Text=<%= section.<header>.<title>.Value %>
    6 Value=<%= section.<header>.<sectionId>.Value %>>
    7 <%= From item In section.<contentItem> _
    8 Select <Node Text=<%= item.<title>.Value %>
    9 Value=<%= item.<itemId>.Value %>/> %>
    10 </Node> %>
    11 </Tree>
    12 rtvSections.LoadXml(xNav.ToString)
    13

    Which returns xml that can be loaded into a tree view control.

    My question is: how can I get the index or position of each section and contentItem from the original document, i.e. can I add an attribute to my nodes that says index="1", section="1.1", etc? 

    I don't want to have to put an index value into the original xml as I'd have to reassign these as people edited the document, adding, deleting and reordering sections and items.

    There doesn't seem to be an Index property for an element or any way of knowing it's the 3rd <section> element in the <sections> element.

    Any help would be really gratefully received, 

    Nick

    Wednesday, October 15, 2008 3:45 PM

Answers

  • Here is an example: assuming we have the following XML

    Code Snippet

    <manual>
      <header>
        <!-- stuff here -->
      </header>
      <sections>
        <section>
          <header>
            <!-- stuff here -->
          </header>
          <contentItem>
            <!-- stuff here -->
          </contentItem>
          <contentItem>
            <!-- stuff here -->
          </contentItem>
          <contentItem>
            <!-- stuff here -->
          </contentItem>
        </section>
        <section>
          <header>
            <!-- stuff here -->
          </header>
          <contentItem>
            <!-- stuff here -->
          </contentItem>
          <contentItem>
            <!-- stuff here -->
          </contentItem>
        </section>
      </sections>
    </manual>

     

     

    then this VB.NET code

    Code Snippet

            Dim content As XElement = XElement.Load("..\..\XMLFile1.xml")
            Dim xNav As XElement = <Tree>
                                       <%= content.<sections>.<section>.Select(Function(s, si) <Node index=<%= String.Format("{0}", si + 1) %>>
                                                                                                   <%= s.<contentItem>.Select(Function(c, ci) <Node section=<%= String.Format("{0}.{1}", si + 1, ci + 1) %>></Node>) %>
                                                                                               </Node>) %>
                                   </Tree>
            xNav.Save(Console.Out)

     

     

    will output

    Code Snippet

    <Tree>
      <Node index="1">
        <Node section="1.1"></Node>
        <Node section="1.2"></Node>
        <Node section="1.3"></Node>
      </Node>
      <Node index="2">
        <Node section="2.1"></Node>
        <Node section="2.2"></Node>
      </Node>
    </Tree>

     

     

    So there is a Select method that provides a zero-based index that can be used. I don't think however you can do that with the query syntax so the example forces you to use the method syntax of LINQ.

    Wednesday, October 15, 2008 4:33 PM

All replies

  • Here is an example: assuming we have the following XML

    Code Snippet

    <manual>
      <header>
        <!-- stuff here -->
      </header>
      <sections>
        <section>
          <header>
            <!-- stuff here -->
          </header>
          <contentItem>
            <!-- stuff here -->
          </contentItem>
          <contentItem>
            <!-- stuff here -->
          </contentItem>
          <contentItem>
            <!-- stuff here -->
          </contentItem>
        </section>
        <section>
          <header>
            <!-- stuff here -->
          </header>
          <contentItem>
            <!-- stuff here -->
          </contentItem>
          <contentItem>
            <!-- stuff here -->
          </contentItem>
        </section>
      </sections>
    </manual>

     

     

    then this VB.NET code

    Code Snippet

            Dim content As XElement = XElement.Load("..\..\XMLFile1.xml")
            Dim xNav As XElement = <Tree>
                                       <%= content.<sections>.<section>.Select(Function(s, si) <Node index=<%= String.Format("{0}", si + 1) %>>
                                                                                                   <%= s.<contentItem>.Select(Function(c, ci) <Node section=<%= String.Format("{0}.{1}", si + 1, ci + 1) %>></Node>) %>
                                                                                               </Node>) %>
                                   </Tree>
            xNav.Save(Console.Out)

     

     

    will output

    Code Snippet

    <Tree>
      <Node index="1">
        <Node section="1.1"></Node>
        <Node section="1.2"></Node>
        <Node section="1.3"></Node>
      </Node>
      <Node index="2">
        <Node section="2.1"></Node>
        <Node section="2.2"></Node>
      </Node>
    </Tree>

     

     

    So there is a Select method that provides a zero-based index that can be used. I don't think however you can do that with the query syntax so the example forces you to use the method syntax of LINQ.

    Wednesday, October 15, 2008 4:33 PM
  • Absolutely spot on!  Thanks  Smile
    Thursday, October 16, 2008 8:30 AM