tags:

views:

54

answers:

1

I have the following Code to display Data from the Database in XML Document

public void generate_XML_AllTables(string Dir)
    {
        SqlDataReader Load_SP_List = null;  //SQL reader that gets list of stored procedures in the database
        SqlDataReader DataclassId = null;   //SQL reader to get the DataclassIds from tables

        SqlConnection conn = null;
        conn = new SqlConnection("Data Source= --SOME DATABASE--; persist security info=False;Trusted_Connection=Yes");

        SqlConnection conn_2 = null;
        conn_2 = new SqlConnection("Data Source= --SOME DATABASE--; persist security info=False;Trusted_Connection=Yes");

        SqlCommand getDataclassId_FromTables;

        int num_SP = 0, num_Tables = 0;
        string strDataClass;    //Name of table
        string sql_str;         //SQL command to get 

        conn.Open();

        //Selecting all Load Stored Procedures of CLNT & Get the table names
        // to pass the Load operation which generates the XML docs.
        SqlCommand cmd = new SqlCommand("Select * from sys.all_objects where type_desc='SQL_STORED_PROCEDURE' and name like 'CLNT%Load';", conn);
        Load_SP_List = cmd.ExecuteReader();

        while (Load_SP_List.Read())
        {
            //Gets the list of Stored Procedures, then modifies it
            //to get the table names
            strDataClass = Load_SP_List[0].ToString();
            strDataClass = strDataClass.Replace("CLNT_", "");
            strDataClass = strDataClass.Replace("_Load", "");
            sql_str = "select DataclassId from " + strDataClass;


            //Gets the DataclassID's from the tables then passes 
            //the parameters to the method Run_Load_StoredProcedure
            //(Table name, DataclassID)
            conn_2.Open();
            getDataclassId_FromTables = new SqlCommand(sql_str, conn_2);
            DataclassId = getDataclassId_FromTables.ExecuteReader();

            while (DataclassId.Read())
            {
                string test = DataclassId[0].ToString();
                Guid oRootGuid = new Guid(test);
                run_Load_StoredProcedure(strDataClass, oRootGuid, Dir);
                num_Tables++;
            }

            DataclassId.Close();
            conn_2.Close();
            num_SP++;
        }

        Load_SP_List.Close();
        conn.Close();
        System.Console.WriteLine("{0} of Stored Procedures have been executed and {1} of XML Files have been generated successfully..", num_SP,num_Tables);

    }

    public string run_Load_StoredProcedure(string strDataClass, Guid guidRootId, string Dir)
    {
        SqlDataReader rdr = null;

        SqlConnection conn = null;
        conn = new SqlConnection("Data Source= --SOME DATABASE--; persist security info=False;Trusted_Connection=Yes");
        conn.Open();

        // Procedure call with parameters
        SqlCommand cmd = new SqlCommand("CLNT_" + strDataClass + "_Load", conn);
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.CommandTimeout = 0;

        //Adding parameters, in- and output
        SqlParameter idParam = new SqlParameter("@DataclassId", SqlDbType.UniqueIdentifier);
        idParam.Direction = ParameterDirection.Input;
        idParam.Value = guidRootId;

        SqlParameter xmlParam = new SqlParameter("@XML", SqlDbType.VarChar, -1 /*MAX*/ );
        xmlParam.Direction = ParameterDirection.Output;

        cmd.Parameters.Add(idParam);
        cmd.Parameters.Add(xmlParam);

        rdr = cmd.ExecuteReader(CommandBehavior.SingleResult);

        DirectoryInfo dest = new DirectoryInfo(Dir + "\\Backup");
        DirectoryInfo source = new DirectoryInfo(Dir);

        if (source.Exists == false)
        {
            source.Create();

            if (dest.Exists == false)
            {
                dest.Create();
            }
        }
        string xmlFile = @Dir + "\\" + strDataClass + " [" + guidRootId + "].xml";

        //The value of the output parameter ‘xmlParam’ will be saved in XML format using the StreamWriter.
        System.IO.StreamWriter wIn = new System.IO.StreamWriter(xmlFile, false);
        wIn.WriteLine(xmlParam.Value.ToString());
        wIn.Close();
        rdr.Close();

        conn.Close();

        return xmlFile;
    }

The problem the generated XML Files are all displayed in One Line. Can someone suggest an edit to make the XMLs in a normal Multi-line format?

EDIT

Here is an example of the generated XML

<CT_MilitaryUsers Version="1" DataSource="Source" ModDttm="2010-07-20T14:13:55.320" ModUser="EUADEV\A003893" ModuleOwner="EUADEVS06\SS2008" CreateDttm="2010-07-20T14:13:55.320" CreateUser="EUADEV\A003893">

  <CtMilitaryUsers DataclassId="8BA475CB-5582-481B-A3DE-099F4E59D323" EntityId="8BA475CB-5582-481B-A3DE-099F4E59D323" Name="CTP" IsExtMilUser="0" />

 </CT_MilitaryUsers><CT_MilitaryUsers Version="1" DataSource="Source" ModDttm="2010-07-    20T14:13:55.320" ModUser="EUADEV\A003893" ModuleOwner="EUADEVS06\SS2008" CreateDttm="2010-07-20T14:13:55.320" CreateUser="EUADEV\A003893"><CtMilitaryUsers DataclassId="8BA475CB-5582-481B-A3DE-099F4E59D323" EntityId="8BA475CB-5582-481B-A3DE-099F4E59D323" Name="CTP" IsExtMilUser="0"/></CT_MilitaryUsers>

it used to be displayed in one line but even now (after using the XDocument) it's still not well formatted

+3  A: 

If the problem is that the source XML string does not include the neccesary formatting, you could load the XML into an XmlDocument and then use that to write to stream with formatting.

Here is a quick example.

  XmlDocument doc = new XmlDocument();
  doc.LoadXml(xmlParam.Value.ToString());

  using (StreamWriter wIn = new StreamWriter(xmlFile, false))
  using (XmlTextWriter wr = new XmlTextWriter(wIn))
  {
    wr.Formatting = Formatting.Indented;
    doc.WriteTo(wr); 
  }
Chris Taylor
It says "Root element is missing" Error!!
Reda
That means that you XML is not a well formed document with a single root node.
Chris Taylor
Is there a solution around it?
Reda
@Reda, well I have not seen the offending XML, but in short the only option really is to correct the XML. If the problem is that the XML is actually multiple XML fragments, then you will need to either format each fragment individually using the XmlDocument or you can put a root element around all the fragments and then format everything and extract the framgments afterwards. But I would need to see the offending XML to be more helpful.
Chris Taylor
they are plenty, I added one to my original post.
Reda
@Reda, this has 2 separate XML fragments. If load that snipet into Visual Studio in an XML file you will see the same error '`XML document cannot contain multiple root level elements`'. For that to be treated as well formed (not formatted) XML you will need to put a single root element arround it all or load each `CT_Military' user element individually.
Chris Taylor
but I though this code retrieves data from the DB automaticaly and "supposedly" saves them into a well formed XML? the thing is my work was build (continues) on this code (I didn't write it myself). Do you say I should edit the original code?
Reda
From a quick look at the details, it would look like each procedure call returns a separate piece of XML and appends it to the file. At no point does there seem to be a single root element written to the file, so the file seems like it is not a valid XML document. However, if you use XmlDocument to format the individual results from the procedure, then the problem is that the XML from the procedure is not valid. So to options could be 1. Write a root start element to the file before writing the results from the procedures and when finished, write a closing root element. Format the file.
Chris Taylor
Cont. Option 2. would be to ensure that each individual procedure result is valid XML by adding a root element to the returned value, then using the XmlDocument to format the XML and then strip the root elements before writing to the file. Bottom line, to use XmlDocument to format the XML, something will need to be fixed to ensure a well formed XML is passed to the XmlDocument.
Chris Taylor
Reda
@Reda, yes that is very possible. If the Xml is loaded into an XmlDocument you can then get the specific Xml element from the XmlDocument and use XmlElement.SetAttribute to set the value of an attribute. Using XmlDocument you can manipulate the entire Xml structure/content quite easily.
Chris Taylor
@Reda, what a coincidence I just answered a question relating to your requirement to manipulate the XmlDocument nodes, this might interest you. http://stackoverflow.com/questions/3663076/select-specific-xml-node-from-xmldocument-then-change-xml-nodes-attribute
Chris Taylor
thx! I ´tried this before on other attributes and it worked fine. I just though that the GUID would be diffirent somehow to modify.. but it seems it's not
Reda