【问题标题】:LINQ to XML - Elements() works but Elements(XName) does not workLINQ to XML - Elements() 有效,但 Elements(XName) 无效
【发布时间】:2020-05-29 18:53:01
【问题描述】:

下面是我的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。

拉贾

【问题讨论】:

    标签: c# xml linq-to-xml


    【解决方案1】:

    您需要考虑命名空间:

    XNamespace df = data.Root.Name.Namespace;
    

    然后使用df + "foo" 在根元素上定义的命名空间中选择本地名称为foo 的元素。

    正如已经提到的,您可能想要选择后代,而不是子元素:

            var elements = from c in data.Descendants(df + "Textbox")
                           select c;
    

    【讨论】:

    • +1 用于发现“后代”问题命名空间问题。
    • 感谢您的回答,但我为什么需要命名空间?
    • 如果 XML 输入使用命名空间,那么使用 System.Xml.Linq 中的 XML API,您需要通过将 XNamespace“添加”到具有本地名称的字符串来构造 XName
    • 我会将你添加到联系人中作为救生员
    【解决方案2】:

    在这种情况下,您正在寻找 Descendants() 而不是 Elements()Elements() 只选择直系子代。

    文档

    注意:根据您的示例代码,使用Descendants() 仍会引发异常,因为并非所有ReportItems 元素都具有Name 属性。你需要做类似Console.WriteLine("Element : " + (element.Attributes("Name").Any() ? element.Attribute("Name").Value : "(no name)") );

    【讨论】:

    • 你只解决了一半的问题——这里也存在命名空间问题。
    • 谢谢:-)...您的解决方案澄清了很多歧义+1
    • @Rob Levine,你确定吗?这似乎没有必要,但也许我错过了一些东西。启发我。
    • OP 提供的 xml 位于“schemas.microsoft.com/sqlserver/reporting/2008/01/…”的命名空间中(在第一行向右滚动)。这意味着尽管您正确识别了后代问题,但 OP 对 data.Descendants("ReportItems") 的调用仍然不会返回任何内容,因为这是在“null”命名空间中搜索 ReportItems。它需要以命名空间为前缀(参见 Martin 的回答),或者如下所示: data.Descendants(XName.Get("ReportItems", "schemas.microsoft.com/sqlserver/reporting/2008/01/…" )
    【解决方案3】:
     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(),它可能会起作用

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-27
      • 2011-06-12
      • 2017-06-10
      • 1970-01-01
      相关资源
      最近更新 更多