In an earlier post, I described what type of object model you get when you provide a relatively simple XML structure. A customer asked what happens when you have a more complicated nested XML, such as the following fictitious structure?

<?xml version="1.0"?>
<book>
    <frontmatter />
    <chapter>
        <section>
            <paragraphs>
                <paragraph>Chapter 1, Section 1, Paragraph 1</paragraph>
                <paragraph>Chapter 1, Section 1, Paragraph 2</paragraph>
            </paragraphs>
        </section>
        <section>
            <paragraphs>
                <paragraph>Chapter 1, Section 2, Paragraph 1</paragraph>
                <paragraph>Chapter 1, Section 2, Paragraph 2</paragraph>
            </paragraphs>
        </section> 
    </chapter>
    <chapter>
        <section>
            <paragraphs>
                <paragraph>Chapter 2, Section 1, Paragraph 1</paragraph>
                <paragraph>Chapter 2, Section 1, Paragraph 2</paragraph>
            </paragraphs>
        </section>
        <section>
            <paragraphs>
                <paragraph>Chapter 2, Section 2, Paragraph 1</paragraph>
                <paragraph>Chapter 2, Section 2, Paragraph 2</paragraph>
            </paragraphs>
        </section>
    </chapter>
</book>

In Microsoft Office Word for example, Microsoft Visual Studio Tools for the Microsoft Office System, Version 2.0 would generate the following objects:

  • BookNode (of type Microsoft.Word.Tools.Word.XMLNode
  • BookFrontMatterNode (of type Microsoft.Word.Tools.Word.XMLNode
  • BookChapterNodes (of type Microsoft.Word.Tools.Word.XMLNodes
  • ChapterSectionNodes (of type Microsoft.Word.Tools.Word.XMLNodes
  • SectionParagraphNodes (of type Microsoft.Word.Tools.Word.XMLNodes
  • ParagraphicsParagraphNodes (of type Microsoft.Word.Tools.Word.XMLNodes)

Notice that the nesting in the automatically-generated objects here is only two levels deep.

To further illustrate, here's some C# code that provides insight as to how this works programmatically:

private void ThisDocument_Initialize(object sender, System.EventArgs e)
{
    // Prints 2 (<chapters>). 
    MessageBox.Show(this.BookChapterNodes.Count.ToString()); 
    // Prints 4 (<sections>).
    MessageBox.Show(this.ChapterSectionNodes.Count.ToString()); 
    // Prints 4 (<paragraphs>).
    MessageBox.Show(this.SectionParagraphsNodes.Count.ToString());
    // Prints 8 (<paragraph>).  
    MessageBox.Show(this.ParagraphsParagraphNodes.Count.ToString());

    foreach (Word.XMLNode node in this.ParagraphsParagraphNodes)
    { 
        // Prints "Chapter 1, Section 1, Paragraph 1" and so on. 
        MessageBox.Show(node.Text); 
    }
   
    // Each of these equivalent lines of code
    // print "Chapter 2, Section 2, Paragraph 2."
    MessageBox.Show(this.BookNode.ChildNodes[3].ChildNodes[2].
        ChildNodes[1].ChildNodes[2].Text);
    MessageBox.Show(this.BookChapterNodes[2].ChildNodes[2].
        ChildNodes[1].ChildNodes[2].Text);
    MessageBox.Show(this.ChapterSectionNodes[4].ChildNodes[1].
        ChildNodes[2].Text);
    MessageBox.Show(this.SectionParagraphsNodes[4].ChildNodes[2].Text);
    MessageBox.Show(this.ParagraphsParagraphNodes[8].Text);
}

-- Paul Cornell

-----
This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at http://www.microsoft.com/info/cpyright.htm.