将 xmlns 属性添加到根元素

Posted

技术标签:

【中文标题】将 xmlns 属性添加到根元素【英文标题】:Add xmlns attribute to root element 【发布时间】: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">

【问题讨论】:

【参考方案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 标记的原因是因为您没有在同一命名空间中创建所有子节点。

    要将元素放入默认命名空间,请创建XNamespace(请参阅下面的ns1)并将值添加到元素名称之前。例如:new XElement(ns1 + "Report"); 这会在 ns1 命名空间中创建一个元素 &lt;Report&gt;,并且没有前缀。

    要添加其他命名空间,请添加带有命名空间和前缀的属性。例如,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", "")。子项中缺少名称空间,因此它们最终会出现在空名称空间中。

以上是关于将 xmlns 属性添加到根元素的主要内容,如果未能解决你的问题,请参考以下文章

为啥 XContainer.Add 方法无论如何都会向添加的元素添加“xmlns”属性,我该如何阻止这种行为?

如果元素具有 xmlns 属性,Xpath 将失败 [重复]

添加空的默认 XML 命名空间 xmlns="" 属性?

如何使用 XSLT 为所有元素和属性添加名称空间和前缀?

无法将“xmlns”属性添加到 sitemap.xml 中的 urlset

vue实现将某个dom元素或组件挂载到根节点