使用XElement重定义XML命名空间别名报错的解决方法咨询
解决Linq to XML中命名空间前缀重定义的报错问题
你遇到的问题是Linq to XML不允许在元素上下文里重复定义同一个前缀的不同命名空间映射——具体来说,你先在父元素<P>里把ab前缀映射到了2010的命名空间,然后又试图给子元素<ab:Ex>添加一个同名前缀的属性,指向2013的命名空间,这就触发了Linq to XML的冲突检查,抛出了你看到的错误。
问题根源
你创建<ab:Ex>元素时用的是2010版本的ab命名空间,然后又试图给这个元素添加xmlns:ab属性来重定义,Linq to XML会认为这是在同一个元素的上下文里重复定义前缀,所以报错。实际上我们需要让<ab:Ex>元素本身属于2013的命名空间,同时显式重定义前缀。
解决方案
我们可以拆分命名空间的定义,直接给<ab:Ex>元素指定2013的命名空间,再添加前缀重定义属性。修改后的代码如下:
using System.Xml.Linq; namespace xmltest { class Program { static void Main(string[] args) { // 加载现有XML(这部分没问题) XDocument doc1 = XDocument.Load(@"c:\simple.xml", LoadOptions.None); System.Console.WriteLine(doc1.ToString()); // 创建新XML的正确方式 XNamespace nsx = "http://schemas.microsoft.com/x/2010/manifest"; // 分别定义两个版本的ab命名空间 XNamespace ab2010 = "http://schemas.microsoft.com/a/2010/manifest"; XNamespace ab2013 = "http://schemas.microsoft.com/a/2013/manifest"; XNamespace ac = "http://schemas.microsoft.com/a/2013/manifest"; XDocument doc2 = new XDocument( new XDeclaration("1.0", "utf-8", ""), new XElement(nsx + "P", new XAttribute("xmlns", nsx.NamespaceName), new XAttribute(XNamespace.Xmlns + "ab", ab2010.NamespaceName), new XAttribute(XNamespace.Xmlns + "ac", ac.NamespaceName), // 直接用2013的命名空间创建Ex元素,同时添加前缀重定义属性 new XElement(ab2013 + "Ex", new XAttribute(XNamespace.Xmlns + "ab", ab2013.NamespaceName) ) ) ); System.Console.WriteLine(doc2.ToString()); } } }
代码说明
- 把原来的
ab命名空间拆成了ab2010(父元素的映射)和ab2013(子元素要用的),避免命名混淆 - 创建
<ab:Ex>元素时,直接使用ab2013命名空间,这样元素的实际命名空间是2013版本 - 给子元素添加
xmlns:ab="http://schemas.microsoft.com/a/2013/manifest"属性,完成前缀的重定义——因为这个属性是在子元素上,和父元素的ab前缀映射属于不同的元素上下文,所以不会触发冲突检查
运行这段代码后,生成的XML就会和你想要的完全一致:
<P xmlns="http://schemas.microsoft.com/x/2010/manifest" xmlns:ab="http://schemas.microsoft.com/a/2010/manifest" xmlns:ac="http://schemas.microsoft.com/a/2013/manifest"> <ab:Ex xmlns:ab="http://schemas.microsoft.com/a/2013/manifest"> </ab:Ex> </P>
内容的提问来源于stack exchange,提问作者Andreas Nick
相关产品推荐
相关产品推荐

