LINQ to XML - Elements()可以工作,但Elements(XName)无法工作。

14
以下是我的 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>

我希望能够获取所有文本框(Textbox)的名称和值。以下是我尝试的代码,但它并不起作用:
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();

但是当我将查询更改为以下内容时:
var elements = from c in data.Elements().Elements().ElementAt(0).Elements().ElementAt(0).Elements()
                           select c;

它起作用了。

非常感谢在这方面的任何帮助。

编辑:在答案的帮助下,我成功地获得了期望的结果。非常感谢你们:)

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

3个回答

35

您需要考虑命名空间:

XNamespace df = data.Root.Name.Namespace;
然后使用df + "foo"来选择在根元素上定义的命名空间中具有本地名称foo的元素。
正如已经提到的,您可能想选择后代而不是子元素:
        var elements = from c in data.Descendants(df + "Textbox")
                       select c;

谢谢您的回答,但我为什么需要命名空间呢? - Mina Gabriel
如果XML输入使用命名空间,则需要使用System.Xml.Linq中的XML API,通过将XNamespace添加到具有本地名称的字符串中来构造XName。 - Martin Honnen

4
在这种情况下,您应该使用Descendants()而不是Elements()Elements()仅选择直接子元素。 文档 注意:根据您的示例代码,即使使用Descendants()也会引发异常,因为并非所有的ReportItems元素都有Name属性。 您需要执行类似于Console.WriteLine("Element : " + (element.Attributes("Name").Any() ? element.Attribute("Name").Value : "(no name)") );的操作。

你只解决了一半的问题 - 这里还有一个命名空间问题。 - Rob Levine
@Rob Levine,你确定吗?看起来好像不必要,但也许我漏掉了什么。启发一下我吧。 - smartcaveman

0
 if (openFileDialog1.ShowDialog() == DialogResult.OK)
        {
            filepath = openFileDialog1.FileName;
            try
            {

                XElement xe = XElement.Load(filepath);
              // 

                string sql = "insert OR IGNORE into price_list (name,his_code,specs,unit,spell,price) values(@name,@his_code,@specs,@unit,@spell,@price);";
                int count = 0;
                foreach (XElement el in xe.Descendants("row"))
                {
                    SQLiteParameter[] ps =
                    {
                        new SQLiteParameter("@his_code",el.Element("aka079").Value),
                        new SQLiteParameter("@name",el.Element("aka061").Value),
                        new SQLiteParameter("@specs",el.Element("aka073").Value),
                        new SQLiteParameter("@unit",el.Element("aka067").Value),
                        new SQLiteParameter("@spell",SpellCode.GetSpellCode(el.Element("aka061").Value)),
                        new SQLiteParameter("@price",el.Element("aka071").Value),
                    };

                    if (SqliteHelper.ExecuteNonQuery(sql, ps) > 0)
                    {
                        count++;
                    }

                }

            }
            catch (Exception ex)
            {
                MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
            }

只需将XElements()更改为Descendants(),它就可以正常工作了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接