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

使用LINQ-to-XML如何避免Descendants返回冗余命名空间并保留前缀

解决方法:保留前缀但去除重复命名空间声明的XML节点获取

方案1:使用XmlWriter控制命名空间输出

LINQ to XML的XElement.ToString()默认会为节点添加必要的命名空间声明,哪怕上层已经存在。通过XmlWriterSettings的NamespaceHandling.OmitDuplicates配置,可以省略重复的命名空间声明,输出和原XML一致的片段:

string soapEnvelopeXml = @"<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:gdp=""http://example.com/asdf"">
   <soapenv:Header/>
   <soapenv:Body>
      <gdp:GetLotNum/>
   </soapenv:Body>
</soapenv:Envelope>";

XElement envelope = XElement.Parse(soapEnvelopeXml);
XNamespace envelopeNs = "http://schemas.xmlsoap.org/soap/envelope/";
var bodyNode = envelope.Descendants(envelopeNs + "Body").FirstOrDefault();

if (bodyNode == null) return null;

var settings = new XmlWriterSettings
{
    OmitXmlDeclaration = true,
    NamespaceHandling = NamespaceHandling.OmitDuplicates,
    Indent = true,
    IndentChars = "   " // 匹配原XML的缩进格式
};

using (var sw = new StringWriter())
using (var writer = XmlWriter.Create(sw, settings))
{
    bodyNode.WriteTo(writer);
    return sw.ToString();
}

原理说明

NamespaceHandling.OmitDuplicates会让XmlWriter自动忽略那些已经在父级节点(或更上层)声明过的命名空间,因此输出的<soapenv:Body>节点不会重复添加xmlns:soapenv和xmlns:gdp声明,仅保留前缀和节点结构。


方案2:使用XmlReader直接读取原始XML片段

如果需要完全匹配原XML的格式(包括空格、缩进),可以用XmlReader定位目标节点后,直接读取其原始XML文本:

string soapEnvelopeXml = @"<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:gdp=""http://example.com/asdf"">
   <soapenv:Header/>
   <soapenv:Body>
      <gdp:GetLotNum/>
   </soapenv:Body>
</soapenv:Envelope>";

using (var reader = XmlReader.Create(new StringReader(soapEnvelopeXml)))
{
    while (reader.Read())
    {
        // 匹配目标节点:命名空间+本地名
        if (reader.NodeType == XmlNodeType.Element && 
            reader.NamespaceURI == "http://schemas.xmlsoap.org/soap/envelope/" && 
            reader.LocalName == "Body")
        {
            // 读取节点的原始外部XML
            return reader.ReadOuterXml();
        }
    }
}
return null;

原理说明

ReadOuterXml()直接从输入的XML字符串中截取目标节点的原始文本,完全保留原有的前缀、格式和缩进,不会生成新的命名空间声明。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 18:14:56