Linq XML 使用属性中的特定值查询父级的后代

Posted

技术标签:

【中文标题】Linq XML 使用属性中的特定值查询父级的后代【英文标题】:Linq XML query the descendants of parent with a specific value in attribute 【发布时间】:2020-04-25 19:46:54 【问题描述】:

我需要一些关于 LINQ to XML 的帮助。我有以下 XML;

<GcctTestData>
  <TestDriveRequest Record="1">
    <element name="Time Zone">(GMT+05:30)</element>
    <element name="Requested Dealer">Concorde</element>
    <element name="Model Year">1999</element>
    <element name="Make">Tata</element>
    <element name="Model/Vehicle Line">Indica</element>
  </TestDriveRequest>
  <TestDriveRequest Record="2">
    <element name="Time Zone">(GMT+05:30)</element>
    <element name="Requested Dealer">Kun"</element>
    <element name="Model Year">2020"</element>
    <element name="Make">BMW"</element>
    <element name="Model/Vehicle Line">3-series</element>
  </TestDriveRequest>
  <TestDriveRequest Record="3">
    <element name="Time Zone">(GMT+05:30)</element>
    <element name="Requested Dealer">KUN Hyundai</element>
    <element name="Model Year">2001</element>
    <element name="Make">Hyundai</element>
    <element name="Model/Vehicle Line">Verna</element>
  </TestDriveRequest>
</GcctTestData>

我试过如下:

IEnumerable<XElement> xElements =
                from element in root.Elements("TestDriveRequest")
                where element.Attribute("Record").Value == "1"
                select element;

            foreach (XElement el in xElements.Descendants().Where(p => !p.HasElements))
            
                int keyInt = 0;
                string keyName = el.Attribute("name").Value;

                while (keyValuePairs.ContainsKey(keyName))
                
                    keyName = $"el.Attribute("name").Value_keyInt++";
                
                keyValuePairs.Add(keyName, el.Value);
                            

我必须为具有记录值 1

的父元素获取 元素 的元素 name 属性值>

但是 linq 查询没有获取它...

实施@anu-viswan 的建议后,我面临以下问题

【问题讨论】:

【参考方案1】:

您需要使用root.Descendants 而不是root.Elements

例如,

IEnumerable<XElement> xElements =   from element in root.Descendants("TestDriveRequest")
                where element.Attribute("Record").Value == "1"
                select element;

XContainer.Elements

返回此元素的子元素的过滤集合或 文件,按文件顺序。仅具有匹配 XName 的元素 包含在集合中。

XContainer.Descendants

为此返回一个过滤后的后代元素集合 文档或元素,按文档顺序。只有元素具有 匹配的 XName 包含在集合输出中

完整代码

IEnumerable<XElement> xElements =   from element in root.Descendants("TestDriveRequest")
            where element.Attribute("Record").Value == "1"
            select element;

foreach (XElement el in xElements.Descendants().Where(p => !p.HasElements))

   int keyInt = 0;
   string keyName = el.Attribute("name").Value;

   while (keyValuePairs.ContainsKey(keyName))
   
     keyName = $"el.Attribute("name").Value_keyInt++";
   
   keyValuePairs.Add(keyName, el.Value);
  

样本输出

【讨论】:

现在我遇到了错误 System.NullReferenceException: Object reference not set to an instance of an object. 在这一行 foreach (XElement el in xElements. Descendants().Where(p => !p.HasElements))【参考方案2】:

这就是我创建字典的方式:

using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace AscendingSequences

    class AscendingSequences
    
        const string FILENAME = @"c:\temp\test.xml";
        public static void Main(string[] args)
        
            XDocument doc = XDocument.Load(FILENAME);

            Dictionary<int, Dictionary<string, string>> dict = doc.Descendants("TestDriveRequest")
                .GroupBy(x => (int)x.Attribute("Record"), y => y.Elements("element")
                    .GroupBy(a => (string)a.Attribute("name"), b => (string)b)
                    .ToDictionary(a => a.Key, b => b.FirstOrDefault()))
                    .ToDictionary(x => x.Key, y => y.FirstOrDefault());
        
    

【讨论】:

以上是关于Linq XML 使用属性中的特定值查询父级的后代的主要内容,如果未能解决你的问题,请参考以下文章

Linq 查询以返回具有特定属性值的嵌套数组

在 C# 中的 XML 中获取上一级父级的节点值

使用 LINQ 的 xml 中特定属性值的列表

使用 LINQ 和 XElement 查询 SQL 表

使用 LINQ 从 XML 获取三个输入中的最大属性值

使用MySQL 8.0递归CTE查找层次结构表中的直接后代并传播给父级