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

Posted

技术标签:

【中文标题】使用 LINQ 的 xml 中特定属性值的列表【英文标题】:List of specific attribute's value in xml using LINQ 【发布时间】:2020-04-01 03:11:34 【问题描述】:
    <?xml version="1.0"?>
    <Rules>
        <Rule id="001">
            <Rule1> name="name1" ruleAttrib="rule1Attribute"</Rule1>
            <Rule2> name="name2" </Rule2>
        </Rule>

        <Rule id="002">
            <Rule3>name="name3"</Rule3>
            <Rule4>name="name4"</Rule4>
            <Rule5>name="name5" ruleAttrib="rule2Attribute"</Rule5>
        </Rule>

        <Rule id="003">
            <Rule6>name="name6"</Rule6>
            <Rule7>name="name7" ruleAttrib=""</Rule7>
        </Rule>

        <Rule id="004">
            <Rule8>name="name8"</Rule8>
            <Rule9>name="name9" </Rule9>
        </Rule>

        <Rule id="005" />

        <Rule id="006">
            <Rule10>name="name10"</Rule10>
            <Rule11>name="name11" ruleAttrib="rule4Attribute"</Rule11>
            <Rule12>name="name12"</Rule12>
        </Rule>
    </Rules>

无法打印特定属性的属性值列表,例如(“ruleAttrib”)

预期输出列表:-

    rule1属性 rule2属性 [空白] rule4Attribute

索引 3 上方为空,因为 id = 003 的规则包含不包含任何内容的 ruleAttrib。

尝试过的代码:-

XDocument xdoc = new XDocument.Load(xmlPath);
List<XElement> ruleGroupList = xdoc.Descendants("Rule").ToList();

foreach (var item in ruleGroupList)
        
            if (item.Descendants().Attributes("ruleAttrib").exist)
            
                List<XAttribute> ruleAttriblist = item.Descendants().Attributes("ruleAttrib").ToList();
                Console.WriteLine(ruleAttriblist );
             
          
        Console.ReadLine();

【问题讨论】:

你得到了什么? 无法应用条件逻辑...在 if 语句中尝试的代码只是条件语句而不是适用的语法,找不到“exist”的替换 您的 xml 是否正确?我看到未关闭标签&lt;Rule12&gt;ruleAttrib 不是xml 属性,它只是节点中的文本。 这些值不是属性。它们在内部文本中。 【参考方案1】:

尝试以下使用 xml linq 和正则表达式:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Text.RegularExpressions;

namespace ConsoleApplication1

    class Program
    
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        
            XDocument doc = XDocument.Load(FILENAME);
            var results = doc.Descendants()
                .Where(x => (x.NodeType == XmlNodeType.Element) && (x.Elements().Count() == 0))
                .Select(x => GetAttributes((string)x))
                .Where(x => x != null)
                .Select(x => new  name = x.Groups["name"].Value, rule = x.Groups["rule"].Value )
                .ToList();
        
        static Match GetAttributes(string innertext)
        
            string pattern = "name=\"(?'name'[^\"]+)\"\\s+ruleAttrib=\"(?'rule'[^\"]*)";
            Match match = Regex.Match(innertext, pattern);
            if (!match.Success) match = null;

            return match;
        
    

【讨论】:

【参考方案2】:

ruleAttribute 不是属性,而是元素的值(内部文本)。

您可以使用Linq 解析Element (Rulexx),然后使用Regex 解析与ruleAttrib 关联的值。

List<XElement> ruleGroupList = xdoc.Root.Descendants("Rule").ToList();
var regex = new Regex("ruleAttrib='(?<value>\\S*)'");
var result = ruleGroupList.Elements()
                          .Select(x=>x.Value)
                          .Where(x=> regex.IsMatch(x))
                          .Select(x=>regex.Match(x).Groups["value"].Value);

输出

如果你想使用“1.rule1Attribute”格式,那么你可以使用

var result = ruleGroupList.Elements()
                          .Select(x=>x.Value)
                          .Where(x=> regex.IsMatch(x))
                          .Select((x,index)=>$"index+1.regex.Match(x).Groups["value"].Value");

【讨论】:

【参考方案3】:
        foreach (var item in ruleGroupList)
        

            if (item.Descendants().Attributes("ruleAttrib").Count() != 0)
            
                List<XAttribute> ruleAttriblist  = item.Descendants().Attributes("ruleAttrib").ToList();
                
                foreach (var attrib in ruleAttriblist)
                
                    Console.WriteLine(attrib.Value);
                
            

        
        Console.ReadLine();

工作正常...按照预期的输出。

【讨论】:

在主节点中找不到 ruleAttrib 所以删除 if 条件并放置在嵌套的内循环中 这可以编译吗??两个循环使用相同的变量项 是的..它编译...两者都在不同的范围内 这很有趣。你能解释一下两者在不同的范围内吗?

以上是关于使用 LINQ 的 xml 中特定属性值的列表的主要内容,如果未能解决你的问题,请参考以下文章

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

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

使用 linq 返回对象的特定属性列表

如何使用 LINQ 选择具有最小或最大属性值的对象

使用正则表达式从字符串中删除属性值不是特定值的所有 xml 节点

查找是不是在列表中找到具有特定属性值的元素