如何使用LINQ-to-XML检测<chkr>中除<ab><tt>外的重复子标签
用LINQ-to-XML找出节点中重复的非/子标签
没问题,我来帮你搞定这个XML处理需求。咱们先再明确一下目标:遍历每个<chkr>父节点,排除掉<ab>和<tt>这两种子标签,然后找出在同一个<chkr>里出现多次的其他标签名——就像示例里<chkr id="3">里的<foo>,出现了两次,正好符合要求。
下面直接上可运行的C#代码,我会一步步解释逻辑:
using System; using System.Linq; using System.Xml.Linq; class Program { static void Main() { // 这里可以替换成从文件加载:XDocument.Load("你的XML文件路径") string xmlContent = @"<?xml version=""1.0"" encoding=""utf-8""?> <random> <chkr id=""1""> <ab>10.100.101.18</ab> <xy>5060</xy> <tt>pop</tt> <qq>pop</qq> </chkr> <chkr id=""2""> <ab>tarek</ab> <tt>tarek</tt> <ab>ffff</ab> <foo>pop</foo> </chkr> <chkr id=""3""> <ab>adf</ab> <foo>adf</foo> <tt>fadsf</tt> <ab>fadsf</ab> <tt>036</tt> <foo>.3</foo> <ssd>wolk</ssd> </chkr> </random>"; XDocument doc = XDocument.Parse(xmlContent); // 核心LINQ查询逻辑 var duplicateTags = doc.Descendants("chkr") .Select(chkr => new { ChkrId = chkr.Attribute("id")?.Value, // 筛选+分组+找重复的核心步骤 DuplicateTagNames = chkr.Elements() // 先排除掉<ab>和<tt>标签 .Where(e => e.Name.LocalName != "ab" && e.Name.LocalName != "tt") // 剩下的标签按名称分组 .GroupBy(e => e.Name.LocalName) // 只保留出现次数>1的分组 .Where(g => g.Count() > 1) // 提取分组的标签名 .Select(g => g.Key) .ToList() }) // 过滤掉没有重复标签的chkr节点,避免空输出 .Where(result => result.DuplicateTagNames.Any()); // 输出结果 foreach (var result in duplicateTags) { Console.WriteLine($"chkr id={result.ChkrId} 包含重复的非ab/tt标签: {string.Join(", ", result.DuplicateTagNames)}"); } } }
代码逻辑拆解:
- 加载XML:这里用
XDocument.Parse解析字符串,如果你是从本地文件读取,换成XDocument.Load("文件路径")就行。 - 遍历所有
节点 :用Descendants("chkr")直接拿到所有目标父节点。 - 筛选并分组子标签:
- 先用
Where排除掉<ab>和<tt>; - 剩下的标签按名称分组,用
GroupBy把相同标签名的元素归为一组; - 筛选出分组内元素数量大于1的组,这些就是重复的标签;
- 先用
- 整理结果:把每个
<chkr>的ID和对应的重复标签名存起来,最后只保留有重复标签的节点,避免输出无效内容。 - 输出:遍历结果打印,示例里只会输出
chkr id=3 包含重复的非ab/tt标签: foo,完全符合预期。
额外提示:
如果你的XML带有命名空间,把e.Name.LocalName换成e.Name == XNamespace.Get("你的命名空间URI") + "标签名"的形式就行,比如e.Name == XNamespace.Get("http://example.com") + "foo"。
内容的提问来源于stack exchange,提问作者Bumba
相关产品推荐
相关产品推荐

