5

I have C# Program to Generate RDL File For whitch Show report in Reporting services. I use Linq to Xml to generate Xml.

When I try to add xmlns XAttribute to Report Element, I encounter several problems.

I test following methods:

first:

        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",

this is a part of my code witch show how generate xml:

second:

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",...

The first method returns an Error and second method adds attribute xmlns to all child node.

I want this format:

<Report xmlns="http://schemas.microsoft.com/sqlserver/reporting/2010/01/reportdefinition">
Amir Reza
  • 435
  • 1
  • 7
  • 15

2 Answers2

4

Try to add you child nodes using the XNamespace as described in 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"));

This should give you the desired result.

You can also add a default namespace by adding an xmlns attribute

XElement xe = new XElement(reportDef + "Report",
    new XAttribute("xmlns", "http://schemas.microsoft.com/sqlserver/reporting/2010/01/reportdefinition"),
    new XElement(reportDef + "Child", "child content"));
Filburt
  • 17,626
  • 12
  • 64
  • 115
  • 1
    I use this solution but Unfortunately as before this attribute add to all child nodes. – Amir Reza May 12 '12 at 08:41
  • Seems odd since I can't reproduce this. Try adding the default namespace attribute as in my second example. Maybe update your question and show more of your actual code. – Filburt May 12 '12 at 08:59
  • If you have any example like this please send it for me. – Amir Reza May 13 '12 at 11:19
1

You can see from @Filburt's answer and this post, that xmlns attribute is a special attribute. It can only be accessed through XNamespace class.

Below I will give you an example on how to create namespaces. You should look at How to: Create a Document with Namespaces for more information. The reason your code is adding xmlns tags to all the children is because you are not creating all child nodes in the same namespace.

  1. To put elements in the default namespace, create a XNamespace (see ns1 below) and prepend the value to the element name. Ex: new XElement(ns1 + "Report"); This creates an element <Report> in the ns1 namespace and doesn't have a prefix.
  2. To add additional namespaces, add an attribute with the namespace and prefix. For example, new XAttribute(XNamespace.Xmlns + "ns2", ns2) adds a namespace to the <Report> element with the ns2 prefix. After this, each time you create an element (new XElement(ns2+"DataSources")) with the ns2 namespace, the prefix will be used. The prefix can be used in all the descendants below the element with the prefix declaration. This is where you made a mistake.

        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());
    
Community
  • 1
  • 1
user845279
  • 2,794
  • 1
  • 20
  • 38
  • Yes all child node create same way. I edit first and second sample Code. please check it. thanks – Amir Reza May 13 '12 at 10:45
  • @AmirReza I've added an example and noted your mistake. Basically, you needed to put `new XElement(reportDef+"DataSources", "")` instead of `new XElement("DataSources", "")`. The namespace was missing in the children so they'd end up in the empty namespace. – user845279 May 14 '12 at 06:42