将不同的 xml 命名空间重新定义为现有别名时出错,将 XElement 与 System.Xml.Linq 结合使用



我尝试将以下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>

现在,一个元素重新定义了命名空间:

xmlns:ab="http://schemas.microsoft.com/a/2013/manifest". 

如何将元素放入我的程序中?这显然是有效的,因为我可以像这样加载 xml 文件:

Add(new XAttribute (XNamespace.Xmlns + "ab")

我收到错误消息:

System.Xml.XmlException:"前缀'ab'不能在同一起始元素标签中从'http://schemas.microsoft.com/a/2010/manifest'重新定义为'http://schemas.microsoft.com/a/2013/manifest'。

实际上是合乎逻辑的(重新定义(,但是当我加载文档时,该元素被接受。

using System.Xml.Linq;
namespace xmltest
{
    class Program
    {
        static void Main(string[] args)
        {
            //Load
            XDocument doc1 = XDocument.Load(@"c:simple.xml", LoadOptions.None);
            System.Console.WriteLine(doc1.ToString());
            //Create new
            XNamespace ab = "http://schemas.microsoft.com/a/2010/manifest";
            XNamespace nsx = "http://schemas.microsoft.com/x/2010/manifest";
            XDocument doc2 = new XDocument(new XDeclaration("1.0", "utf-8", ""), 
                new XElement(nsx + "P"));
            doc2.Element(nsx + "P").Add(new XAttribute("xmlns", 
                "http://schemas.microsoft.com/x/2010/manifest"));
            doc2.Element(nsx + "P").Add(new XAttribute(XNamespace.Xmlns + "ab", 
                 "http://schemas.microsoft.com/a/2010/manifest"));
            doc2.Element(nsx + "P").Add(new XAttribute(XNamespace.Xmlns + "ac", 
                 "http://schemas.microsoft.com/a/2013/manifest"));
            XElement xml = new XElement(ab + "Ex");
            //--> Below does not work work
            xml.Add(new XAttribute(XNamespace.Xmlns + "ab",
                 "http://schemas.microsoft.com/a/2013/manifest"));
            doc2.Element(nsx + "P").Add(xml);
            System.Console.WriteLine(doc2.ToString());
        }
    }
}

有人知道如何解决这个问题吗?

理论上,因为

<ab:Ex xmlns:ab="http://schemas.microsoft.com/a/2013/manifest">

实际上意味着 Ex 要在命名空间(2013 年(中定义,您可以通过在新命名空间中定义 Ex 来获得您想要的内容,即:

XNamespace abOld = "http://schemas.microsoft.com/a/2010/manifest";
XNamespace abNew = "http://schemas.microsoft.com/a/2013/manifest";
XNamespace nsx = ...
XElement xml = new XElement(abNew + "Ex");
xml.Add(new XAttribute(XNamespace.Xmlns + "ab", 
                       "http://schemas.microsoft.com/a/2013/manifest"));

但是,重新调整现有命名空间的别名,以便您可以使用相同的别名,这将对将来的维护造成真正的混淆 - 当别名离开范围时,它将恢复到它的旧定义。我建议您至少为 2010 和 2013 命名空间创建不同的、唯一的别名。

此外,除非 Xml 的预期使用者有问题,并且需要特定的别名或命名空间作用域,否则我通常会避免微观管理命名空间别名和命名空间范围 - 让 Linq to Xml 为您管理。

例如,如何只是:

XNamespace abOld = "http://schemas.microsoft.com/a/2010/manifest";
XNamespace abNew = "http://schemas.microsoft.com/a/2013/manifest";
// Build up the document by providing element, attribute + applicable namespaces:
var root = new XElement(abOld + "P", 
    new XElement(abNew + "Ex"));

最新更新