You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# LINQ读取XML节点为空、无法获取带命名空间属性值问题

C# 读取XML两类常见问题修复

问题复现

存在如下XML结构:

<items>
        <item>
            <title>Weź udział w grze historycznej</title>
            <link>https://legionowo.pl/a/wez-udzial-w-grze-historycznej</link>
            <description><![CDATA[<img src="https://legionowo.pl/img/artykuly/4/2022_07/x41594.jpg.pagespeed.ic.9BJkaqvzdK.jpg%22%3E<br><br>]]></description>
            <pubDate>Fri, 01 Jul 2022 09:10:50 +0000</pubDate>
            <media:content url="https://legionowo.pl/img/artykuly/4/2022_07/x41594.jpg.pagespeed.ic.9BJkaqvzdK.jpg" medium="image" />
            <guid isPermaLink="false">https://legionowo.pl/a/wez-udzial-w-grze-historycznej</guid>
        </item>
<items>

编写如下C#方法读取XML:

private async Task _XElementGet()
{
    XElement doc = XElement.Load("C:\\mail.xml");
    List<XElement> list;
    list = (from prod in doc.Elements("item")
            select prod).ToList();
    foreach(XElement item in list)
    {
        Console.WriteLine(item.Name);
    }
}

执行该方法后获取到的item列表为空,但改用XDocument加载XML、调用Descendants("item")查询时可正常获取节点,对应代码如下:

private async Task _XDocumentGet()
{
    XDocument doc = XDocument.Load("C:\\mail.xml");
    List<XElement> list;
    list = (from prod in doc.Descendants("item")
            select prod).ToList();
    foreach(XElement item in list)
    {
        //Console.WriteLine(item.Element("title"));
        Console.WriteLine(item.FirstAttribute.Value);
    }
}

尝试读取media:content节点的属性值时,抛出如下异常:

System.Xml.XmlException: 'The ':' character, hexadecimal value 0x3A, cannot be included in a name.'

无法正常读取该节点的属性值。

原因与修复方案

问题1:XElement.Elements() 返回空列表

核心原因有两点:

  • Elements()方法只会查找当前节点的直接一级子节点,不会递归遍历多层后代节点。XElement.Load()返回的对象是XML的根节点,如果你要找的<item>节点不是根节点的直接子节点(比如XML存在嵌套层级、或者结构不规范导致层级错乱),调用Elements("item")就匹配不到结果;而Descendants()方法会递归遍历当前节点下所有层级的后代节点,所以可以找到目标节点。
  • 给出的示例XML存在结构错误:末尾根节点写的是开标签<items>,没有用闭标签</items>闭合,会导致XML解析时层级错乱,直接影响节点匹配结果。

修复方式:

  1. 先修正XML结构错误,补全根节点的闭合标签,保证XML格式合法。
  2. 不确定节点层级时,直接用Descendants("item")代替Elements("item")做递归查询,兼容不同层级的节点查找场景。
  3. 如果XML声明了默认命名空间,查询时需要传入带对应命名空间的XName,否则也会匹配不到节点。

问题2:读取media:content节点抛出冒号非法异常

核心原因:

  • media:是XML命名空间前缀,不是节点名称的一部分,冒号是前缀和节点本地名的分隔符,直接把"media:content"作为节点名传入查询方法时,LINQ to XML会把整个字符串当做节点名称处理,自然会抛出名称不能包含冒号的异常。
  • 示例XML中使用了media:前缀,但没有在根节点声明前缀对应的命名空间地址,本身就是不合法的XML结构。RSS场景下media前缀对应的标准命名空间为http://search.yahoo.com/mrss/。

修复方式:

  1. 先在XML根节点补上media前缀的命名空间声明,修正后的合法XML结构如下:
<items xmlns:media="http://search.yahoo.com/mrss/">
        <item>
            <title>Weź udział w grze historycznej</title>
            <link>https://legionowo.pl/a/wez-udzial-w-grze-historycznej</link>
            <description><![CDATA[<img src="https://legionowo.pl/img/artykuly/4/2022_07/x41594.jpg.pagespeed.ic.9BJkaqvzdK.jpg"><br><br>]]></description>
            <pubDate>Fri, 01 Jul 2022 09:10:50 +0000</pubDate>
            <media:content url="https://legionowo.pl/img/artykuly/4/2022_07/x41594.jpg.pagespeed.ic.9BJkaqvzdK.jpg" medium="image" />
            <guid isPermaLink="false">https://legionowo.pl/a/wez-udzial-w-grze-historycznej</guid>
        </item>
</items>
  1. 查询带命名空间前缀的节点时,先声明对应的XNamespace对象,通过命名空间对象 + 节点本地名的方式构造查询条件,修复后的完整读取代码如下:
private async Task GetXmlData()
{
    // 声明media前缀对应的命名空间,必须和XML中声明的地址完全一致
    XNamespace mediaNs = "http://search.yahoo.com/mrss/";
    
    XElement doc = XElement.Load("C:\\mail.xml");
    // 递归查询所有item节点
    List<XElement> itemList = doc.Descendants("item").ToList();
    
    foreach(XElement item in itemList)
    {
        Console.WriteLine($"标题:{item.Element("title")?.Value}");
        // 查询media:content节点
        XElement mediaContentNode = item.Element(mediaNs + "content");
        if (mediaContentNode != null)
        {
            // 读取节点属性
            string imgUrl = mediaContentNode.Attribute("url")?.Value;
            string mediaType = mediaContentNode.Attribute("medium")?.Value;
            Console.WriteLine($"配图地址:{imgUrl},媒体类型:{mediaType}");
        }
    }
}

注意点

  • 只要XML节点带命名空间前缀,查询时都不能直接写带冒号的完整名称,必须通过XNamespace构造合法的XName做匹配。
  • 使用XML前缀时必须提前声明对应的命名空间地址,否则XML本身格式不合法,会触发各类解析异常。

内容的提问来源于stack exchange,提问作者Software_Architect

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 03:20:02