Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LINQ to XML - Elements() works but Elements(XName) does not work

Given below is my xml:

<?xml version="1.0" encoding="utf-8"?>
<Report xmlns:rd="http://schemas.microsoft.com/SQLServer/reporting/reportdesigner" xmlns="http://schemas.microsoft.com/sqlserver/reporting/2008/01/reportdefinition">
    <Body>
        <ReportItems>
            <Textbox Name="txtCurrentDate">
                <CanGrow>true</CanGrow>
                <KeepTogether>true</KeepTogether>
                <Paragraphs>
                    <Paragraph>
                        <TextRuns>
                            <TextRun>
                                <Value>=Today()</Value>
                                <Style>
                                    <FontWeight>Medium</FontWeight>
                                    <Format>d</Format>
                                </Style>
                            </TextRun>
                        </TextRuns>
                        <Style>
                            <TextAlign>Left</TextAlign>
                        </Style>
                    </Paragraph>
                </Paragraphs>
                <Left>0.36958in</Left>
                <Height>0.22917in</Height>
                <Width>1in</Width>
                <Style>
                    <Border>
                        <Style>None</Style>
                    </Border>
                    <PaddingLeft>2pt</PaddingLeft>
                    <PaddingRight>2pt</PaddingRight>
                    <PaddingTop>2pt</PaddingTop>
                    <PaddingBottom>2pt</PaddingBottom>
                </Style>
            </Textbox>
            <Textbox Name="txtName">
                <CanGrow>true</CanGrow>
                <KeepTogether>true</KeepTogether>
                <Paragraphs>
                    <Paragraph>
                        <TextRuns>
                            <TextRun>
                                <Value>Mark Wilkinson</Value>
                                <Style />
                            </TextRun>
                        </TextRuns>
                        <Style />
                    </Paragraph>
                </Paragraphs>
                <Top>0.22917in</Top>
                <Left>0.36958in</Left>
                <Height>0.20833in</Height>
                <Width>3.22917in</Width>
                <ZIndex>1</ZIndex>
                <Style>
                    <Border>
                        <Style>None</Style>
                    </Border>
                    <PaddingLeft>2pt</PaddingLeft>
                    <PaddingRight>2pt</PaddingRight>
                    <PaddingTop>2pt</PaddingTop>
                    <PaddingBottom>2pt</PaddingBottom>
                </Style>
            </Textbox>
        </ReportItems>
        <Height>6.01667in</Height>
        <Style />
    </Body>
    <Width>7.92333in</Width>   
</Report>

I want to get all the Textbox names and values. This is what I tried and it does not work:

XDocument data = XDocument.Load("..\\..\\testxml.rdl");

            var elements = from c in data.Elements("ReportItems")
                           select c;
            foreach (var element in elements)
            {                
                Console.WriteLine("Element : " + element.Attribute("Name").Value);

            }
            Console.ReadKey();

but when I change the query to something like this

var elements = from c in data.Elements().Elements().ElementAt(0).Elements().ElementAt(0).Elements()
                           select c;

it works.

Any help in this regard is much appreciated.

Edit: With the help of answers I was able to get the desired results. Thank you so much :)

XDocument data = XDocument.Load("..\\..\\testxml.rdl");            
            XNamespace ns = data.Root.Name.Namespace;
            var elements = from c in data.Descendants(ns + "Textbox")
                           select c;
            foreach (var element in elements)
            {                
                Console.WriteLine("Element : " + element.Attribute("Name").Value);                
            }
            Console.ReadKey();

TIA.

Raja

like image 262
Raja Avatar asked Jun 02 '11 12:06

Raja


2 Answers

You need to take the namespace into account:

XNamespace df = data.Root.Name.Namespace;

Then use df + "foo" to select elements with local name foo in the namespace defined on the root element.

And as already mentioned you probably want to select descendants, not child elements:

        var elements = from c in data.Descendants(df + "Textbox")
                       select c;
like image 174
Martin Honnen Avatar answered Oct 24 '22 05:10

Martin Honnen


You are looking for Descendants() not Elements() in this case. Elements() only selects immediate children.

Documentation

  • XContainer.Descendants Method (XName) - Returns a filtered collection of the descendant elements for this document or element, in document order. Only elements that have a matching XName are included in the collection
  • XContainer.Elements Method (XName) - Returns a filtered collection of the child elements of this element or document, in document order. Only elements that have a matching XName are included in the collection.

Note: Based on your sample code, using Descendants() will still throw an exception because not all of the ReportItems elements have a Name attribute. You need to do something like Console.WriteLine("Element : " + (element.Attributes("Name").Any() ? element.Attribute("Name").Value : "(no name)") );

like image 4
smartcaveman Avatar answered Oct 24 '22 07:10

smartcaveman