【问题标题】:Add xmlns attribute to root element将 xmlns 属性添加到根元素
【发布时间】:2012-05-12 07:45:59
【问题描述】:

我有 C# 程序来生成 RDL 文件,以便在报告服务中显示报告。 我使用 Linq to Xml 生成 Xml。

当我尝试将 xmlns XAttribute 添加到报表元素时,我遇到了几个问题。

我测试了以下方法:

第一:

        XDocument d = new XDocument(
           new XDeclaration("1.0", "utf-8", "yes"),
           new XElement("Report",
               new XAttribute(XNamespace.Xmlns + "rd", "http://schemas.microsoft.com/SQLServer/reporting/reportdesigner"),
               new XAttribute(XNamespace.Xmlns + "cl", "http://schemas.microsoft.com/sqlserver/reporting/2010/01/componentdefinition"),
               new XAttribute("xmlns", "http://schemas.microsoft.com/sqlserver/reporting/2010/01/reportdefinition"),
                   new XElement("DataSources", ""),
                   new XElement("DataSets", ""),
                   new XElement("ReportSections",

这是我的代码的一部分,展示了如何生成 xml:

秒:

XNamespace reportDef = "http://schemas.microsoft.com/sqlserver/reporting/2010/01/reportdefinition";
        XDocument d = new XDocument(
           new XDeclaration("1.0", "utf-8", "yes"),
           new XElement(reportDef + "Report",
               new XAttribute(XNamespace.Xmlns + "rd", "http://schemas.microsoft.com/SQLServer/reporting/reportdesigner"),
               new XAttribute(XNamespace.Xmlns + "cl", "http://schemas.microsoft.com/sqlserver/reporting/2010/01/componentdefinition"),
                   new XElement("DataSources", ""),
                   new XElement("DataSets", ""),
                   new XElement("ReportSections",...

第一种方法返回一个错误,第二种方法将属性 xmlns 添加到所有子节点。

我想要这种格式:

<Report xmlns="http://schemas.microsoft.com/sqlserver/reporting/2010/01/reportdefinition">

【问题讨论】:

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


    【解决方案1】:

    尝试使用XNamespace 添加子节点,如How to: Create a Document with Namespaces (C#) (LINQ to XML) 中所述

    XNamespace reportDef = "http://schemas.microsoft.com/sqlserver/reporting/2010/01/reportdefinition";
    XElement root = new XElement(reportDef + "Report",
        new XElement(reportDef + "Child", "child content"));
    

    这应该会给你想要的结果。

    您还可以通过添加xmlns 属性来添加默认命名空间

    XElement xe = new XElement(reportDef + "Report",
        new XAttribute("xmlns", "http://schemas.microsoft.com/sqlserver/reporting/2010/01/reportdefinition"),
        new XElement(reportDef + "Child", "child content"));
    

    【讨论】:

    • 我使用这个解决方案,但不幸的是,这个属性像以前一样添加到所有子节点。
    • 看起来很奇怪,因为我无法重现它。尝试像我的第二个示例一样添加默认命名空间属性。也许更新您的问题并显示更多您的实际代码。
    • 如果你有这样的例子,请发给我。
    【解决方案2】:

    您可以从@Filburt 的回答和this 帖子中看到,xmlns 属性是一个特殊属性。只能通过 XNamespace 类访问。

    下面我将给你一个关于如何创建命名空间的例子。您应该查看How to: Create a Document with Namespaces 了解更多信息。您的代码向所有子节点添加 xmlns 标记的原因是因为您没有在同一命名空间中创建所有子节点。

    1. 要将元素放入默认命名空间,请创建XNamespace(请参阅下面的ns1)并将值添加到元素名称之前。例如:new XElement(ns1 + "Report"); 这会在 ns1 命名空间中创建一个元素 &lt;Report&gt;,并且没有前缀。
    2. 要添加其他命名空间,请添加带有命名空间和前缀的属性。例如,new XAttribute(XNamespace.Xmlns + "ns2", ns2) 将命名空间添加到具有 ns2 前缀的 &lt;Report&gt; 元素。此后,每次使用 ns2 命名空间创建元素 (new XElement(ns2+"DataSources")) 时,都会使用前缀。前缀可以用在具有前缀声明的元素下面的所有后代中。这是你犯错的地方。

          StringBuilder sb = new StringBuilder();
          XmlWriterSettings xws = new XmlWriterSettings();
          xws.OmitXmlDeclaration = true;
          xws.Indent = true;
      
          using (XmlWriter xw = XmlWriter.Create(sb, xws))
          {   
              XNamespace ns1 = "http://schemas.microsoft.com/sqlserver/reporting/2010/01/reportdefinition";
              XNamespace ns2 = "http://schemas.microsoft.com/SQLServer/reporting/reportdesigner";
              XNamespace ns3 = "http://schemas.microsoft.com/sqlserver/reporting/2010/01/componentdefinition";
              XDocument doc = new XDocument(new XDeclaration("1.0", "utf-8", "yes"));
              XElement reportElement = new XElement(ns1 + "Report",
                  new XAttribute(XNamespace.Xmlns + "ns2", ns2),
                  new XAttribute(XNamespace.Xmlns + "ns3", ns3));
              doc.Add(reportElement);
      
              reportElement.Add(new XElement(ns2+"DataSources"));
              reportElement.Add(new XElement(ns3+"DataSets"));
              reportElement.Add(new XElement(ns1+"ReportSections"));
      
              doc.WriteTo(xw);
          }
      
          System.Diagnostics.Debug.Write(sb.ToString());
      

    【讨论】:

    • 是的,所有子节点都以相同的方式创建。我编辑第一个和第二个示例代码。请检查一下。谢谢
    • @AmirReza 我添加了一个示例并指出了您的错误。基本上,您需要输入new XElement(reportDef+"DataSources", "") 而不是new XElement("DataSources", "")。子项中缺少名称空间,因此它们最终会出现在空名称空间中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多