如何在C#中使用XDocument在根元素中生成具有多个名称空间的XML文件?

问题描述

我想使用C#中的XDocument为Outlook加载项生成自定义manifest.xml文件

我当前的XML文件(我现在要生成文件)如下:

<?xml version="1.0" encoding="UTF-8"?>
<OfficeApp xmlns="http://schemas.microsoft.com/office/appforoffice/1.1"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:bt="http://schemas.microsoft.com/office/officeappbasictypes/1.0"
           xmlns:mailappor="http://schemas.microsoft.com/office/mailappversionoverrides"
           xsi:type="MailApp">
  <Id>{0026EAB0-AFBA-43FE-A3FA-C479B6FEECCA}</Id>
  <Version>2.0.0.0</Version>
  <!-- More elements -->
</OfficeApp>

我的主要问题是,我无法向OfficeApp元素添加多个名称空间。

我已经尝试了以下方法

private readonly XNamespace Xsi = "xsi:";
private readonly XNamespace MicrosoftSchemasAppsForOffice = "http://schemas.microsoft.com/office/appforoffice/1.1";
private readonly XNamespace W3 = "http://www.w3.org/2001/XMLSchema-instance";
private readonly XNamespace MicrosoftSchemasOfficeBasicTypes = "http://schemas.microsoft.com/office/officeappbasictypes/1.0";
private readonly XNamespace MicrosoftSchemasMailAppVersion = "http://schemas.microsoft.com/office/mailappversionoverrides";

private XDocument GenerateDocument()
{
    return new XDocument(
      new XDeclaration("1.0","utf-8",null),new XElement("OfficeApp",new XAttribute("xmlns",MicrosoftSchemasAppsForOffice),new XAttribute(XNamespace.Xmlns + "xsi",W3),new XAttribute(XNamespace.Xmlns + "bt",MicrosoftSchemasOfficeBasicTypes),new XAttribute(XNamespace.Xmlns + "mailappor",MicrosoftSchemasMailAppVersion),new XAttribute(Xsi + "type","MailApp"),new XElement("Id","{" + Guid.NewGuid().ToString() + "}"),new XElement("Version","2.0.0.0")
      )
    );
}

这导致了以下异常:

System.Xml.XmlException: 'The prefix '' cannot be redefined from '' to    'http://schemas.microsoft.com/office/appforoffice/1.1' within the same start element tag.'

我也试图替换行

new XAttribute("xmlns",

使用

new XAttribute(XNamespace.Xmlns.NamespaceName,

但这给了我以下异常:

System.Xml.XmlException: 'The ':' character,hexadecimal value 0x3A,cannot be included in a name.'

经过数小时的尝试和失败,我仍然不知道如何正确处理xmlns-namespace。 我究竟做错了什么?我认为我尝试生成的XML代码是有效的,因为它工作得很好。

我很感谢任何提示。谢谢!

解决方法

您的根名称空间不必添加为属性,而仅用作元素的名称空间。此外,还必须将xsi名称空间 value 与type属性一起使用:

private readonly XNamespace MicrosoftSchemasAppsForOffice = "http://schemas.microsoft.com/office/appforoffice/1.1";
private readonly XNamespace W3 = "http://www.w3.org/2001/XMLSchema-instance";
private readonly XNamespace MicrosoftSchemasOfficeBasicTypes = "http://schemas.microsoft.com/office/officeappbasictypes/1.0";
private readonly XNamespace MicrosoftSchemasMailAppVersion = "http://schemas.microsoft.com/office/mailappversionoverrides";

private XDocument GenerateDocument()
{
    return new XDocument(
      new XDeclaration("1.0","utf-8",null),new XElement(MicrosoftSchemasAppsForOffice + "OfficeApp",new XAttribute(XNamespace.Xmlns + "xsi",W3),new XAttribute(XNamespace.Xmlns + "bt",MicrosoftSchemasOfficeBasicTypes),new XAttribute(XNamespace.Xmlns + "mailappor",MicrosoftSchemasMailAppVersion),new XAttribute(W3 + "type","MailApp"),new XElement(MicrosoftSchemasAppsForOffice + "Id","{" + Guid.NewGuid().ToString() + "}"),new XElement(MicrosoftSchemasAppsForOffice + "Version","2.0.0.0")
      )
    );
}
,

在XDocument中尝试正确设置名称空间很困难,因此我通常只解析一个字符串

            string xml = 
                "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
                "<OfficeApp xmlns=\"http://schemas.microsoft.com/office/appforoffice/1.1\"" +
                   " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" +
                   " xmlns:bt=\"http://schemas.microsoft.com/office/officeappbasictypes/1.0\"" +
                   " xmlns:mailappor=\"http://schemas.microsoft.com/office/mailappversionoverrides\"" +
                   " xsi:type=\"MailApp\">" +
                "</OfficeApp>";

            XDocument doc = XDocument.Parse(xml);
            XElement officeApp = doc.Root;
            XNamespace ns = officeApp.GetDefaultNamespace();
            officeApp.Add(new XElement(ns + "Id","{0026EAB0-AFBA-43FE-A3FA-C479B6FEECCA}"));
            officeApp.Add(new XElement(ns + "Version","2.0.0.0"));