使用带有System.Xml.Linq

时间:2018-01-02 10:52:33

标签: c# xml linq linq-to-xml

我尝试将以下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());
        }
    }
}

任何人都知道如何解决这个问题?

1 个答案:

答案 0 :(得分:0)

理论上,因为

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

实际上意味着要在 new 命名空间(2013)中定义Ex,您可以通过在新命名空间中定义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"));
相关问题