如何通过创建未附加元素生成带命名空间的XDocument相关文档
构建带XNamespace的XDOM树时属性命名空间异常问题
我先创建XElement和XAttribute对象构建DOM树,之后再将其添加到XDocument中。但涉及XNamespace时出现了不符合预期的输出,以下是简化的测试代码:
using System; using System.Collections.Generic; using System.Linq; using System.Xml.Linq; namespace XamlTest { internal class Program { private static readonly Dictionary<string, string> XamlNamespaces = new Dictionary<string, string>() { { "xmlns", "http://schemas.microsoft.com/winfx/2006/xaml/presentation" }, { "xmlns:x", "http://schemas.microsoft.com/winfx/2006/xaml" } }; private static readonly Dictionary<string, XNamespace> _ns = XamlNamespaces.Select(ns => new { Key = ns.Key.StartsWith("xmlns:") ? ns.Key.Substring(6) : "", Value = (XNamespace)ns.Value }).ToDictionary(ns => ns.Key, ns => ns.Value); internal static void Main() { CreateDocument(); Console.ReadKey(); } public static void CreateDocument() { XElement root = new XElement(_ns[""] + "Section"); foreach (KeyValuePair<string, XNamespace> ns in _ns) root.Add(new XAttribute(string.IsNullOrEmpty(ns.Key) ? "xmlns" : XNamespace.Xmlns + ns.Key, ns.Value)); XDocument xamlDoc = new XDocument(root); root.Add(CreateTree()); Console.WriteLine(xamlDoc.ToString()); } private static List<XElement> CreateTree() { List<XElement> newElements = []; newElements.Add(new XElement(_ns[""] + "Paragraph", new XAttribute(_ns[""] + "FontSize", "12") )); return newElements; } } }
当前执行结果
<Section xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Paragraph p3:FontSize="12" xmlns:p3="http://schemas.microsoft.com/winfx/2006/xaml/presentation" /> </Section>
预期输出
<Section xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Paragraph FontSize="12"/> </Section>
问题分析与解决
原因
XAML的默认命名空间仅作用于元素,普通属性(如FontSize)不需要绑定命名空间。你给FontSize添加了默认命名空间后,LINQ to XML会将其识别为带命名空间的属性,而根节点的默认命名空间只对元素生效,因此会自动生成新的前缀(如p3)来标记这个属性,导致输出不符合预期。
修复方案
去掉FontSize属性的命名空间绑定,直接使用属性名创建XAttribute即可。修改后的CreateTree方法如下:
private static List<XElement> CreateTree() { List<XElement> newElements = []; newElements.Add(new XElement(_ns[""] + "Paragraph", new XAttribute("FontSize", "12") )); return newElements; }
验证结果
修改后执行代码,输出将符合预期:
<Section xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Paragraph FontSize="12" /> </Section>
额外优化
可以简化命名空间的初始化逻辑,让代码更易读:
private static readonly Dictionary<string, XNamespace> _ns = new() { [""] = "http://schemas.microsoft.com/winfx/2006/xaml/presentation", ["x"] = "http://schemas.microsoft.com/winfx/2006/xaml" };
这样就不需要从原字典中截取键名,直接定义命名空间别名和对应的URI即可。
内容的提问来源于stack exchange,提问作者AxD
相关产品推荐
相关产品推荐

