Почему '[' рассматривается как часть имени XmlElement?

Я пытаюсь написать метод, который будет запрашивать любую таблицу SQLite и возвращать ее содержимое в виде XML:

// Get any table's contents as XML; caveat: table can have at most 25 columns (this can be increased if necessary)
string IHHSDBUtils.GenericSaveDataAndReturnAsXML(string DBTableName)
{
    String xmlOutput = String.Empty;
    String qry = String.Format("SELECT * FROM {0}", DBTableName);
    try // catch
    {
        using (SQLiteConnection conn = new SQLiteConnection(HHSUtils.GetDBConnection()))
        {
            conn.Open();
            XmlDocument doc = new XmlDocument();
            XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", null, null);
            doc.AppendChild(dec); // Create the root element
            XmlElement root = doc.CreateElement("Command");
            doc.AppendChild(root);

            try
            {
                using (SQLiteCommand cmd = new SQLiteCommand(qry, conn))
                {
                    using (SQLiteDataReader rdr = cmd.ExecuteReader())
                    {
                        int colCount = rdr.FieldCount;
                        while (rdr.Read())
                        {
                            // outer val
                            XmlElement tblRec = doc.CreateElement(DBTableName);

                            if (colCount > 0)
                            {
                                String firstCol = rdr[0].ToString();
                                XmlElement _firstCol = doc.CreateElement(rdr[0].ToString()); // 
Will this return the right val?
                                _firstCol.InnerText = firstCol;
                                tblRec.AppendChild(_firstCol);
                            }

                            if (colCount > 1)
                            {
                                String secondCol = rdr[1].ToString();
                                XmlElement _secondCol = doc.CreateElement(rdr[1].ToString());
                                _secondCol.InnerText = secondCol;
                                tblRec.AppendChild(_secondCol);
                            }

                            . . .

                            if (colCount > 25)
                            {
                                String twentysixthCol = rdr[25].ToString();
                                XmlElement _twentysixthCol = 
doc.CreateElement(rdr[25].ToString());
                                _twentysixthCol.InnerText = twentysixthCol;
                                tblRec.AppendChild(_twentysixthCol);
                            }

                            root.AppendChild(tblRec);
                        } // while            
                    } // using (SQLiteDataReader
                } // using (SQLiteCommand
            }
            finally
            {
                xmlOutput = doc.OuterXml;
                doc.Save(String.Format("{0}.xml", DBTableName));
            }
        } // using (SQLiteConnection
    } //  try..catch
    catch (Exception ex)
    {
        String msgInnerExAndStackTrace = String.Format(
            "{0}; Inner Ex: {1}; Stack Trace: {2}", ex.Message, ex.InnerException, 
ex.StackTrace);
        ExceptionLoggingService.Instance.WriteLog(String.Format("From 
HHSDBUtils.GenericSaveDataAndReturnAsXML: {0}", msgInnerExAndStackTrace));
    }
    return xmlOutput;
}

Я передал этому методу имя таблицы, которая содержит менее 25 столбцов (если быть точным, 16), назвав ее (тестирование) следующим образом:

MessageBox.Show(hhsdbutils.GenericSaveDataAndReturnAsXML("Inventory"));

Но вместо того, чтобы вернуть возвышенно правильно сформированный блок xml, я получил это решительное коммюнике:

The '[' character, hexadecimal value 0x5B, cannot be included in a name.; Inner Ex: ; Stack 
Trace: at System.Xml.XmlDocument.CheckName(String name)
   at System.Xml.XmlElement..ctor(XmlName name, Boolean empty, XmlDocument doc)
   at System.Xml.XmlDocument.CreateElement(String prefix, String localName, String namespaceURI)
   at System.Xml.XmlDocument.CreateElement(String name)
   at HHS.SQLiteHHSDBUtils.HHS.IHHSDBUtils.GenericSaveDataAndReturnAsXML(String DBTableName)

У меня есть некоторые значения-заполнители, заключенные в квадратные скобки, как видно из LINQPad:

Это (с такими значениями, как "[CRVid]" в таблице) проблема? Если да, то какие еще "нечетные" символы мне следует избегать, чтобы в столбце содержались значения: "{", "}", "(", ")" и т. Д.?

ОБНОВИТЬ

Я изобразил код, подталкивая большого пальца (получил спину)

string IHHSDBUtils.GenericSaveDataAndReturnAsXML(string DBTableName)
{
    String xmlOutput = String.Empty;
    String qry = String.Format("SELECT * FROM {0}", DBTableName);
    try // catch
    {
        using (SQLiteConnection conn = new SQLiteConnection(HHSUtils.GetDBConnection()))
        {
            conn.Open();
            XmlDocument doc = new XmlDocument();
            XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", null, null);
            doc.AppendChild(dec); // Create the root element
            XmlElement root = doc.CreateElement("Command");
            doc.AppendChild(root);

            // Note that to set the text inside the element,
            // you use .InnerText instead of .Value (which will throw an exception).
            // You use SetAttribute to set attribute
            try
            {
                using (SQLiteCommand cmd = new SQLiteCommand(qry, conn))
                {
                    using (SQLiteDataReader rdr = cmd.ExecuteReader())
                    {
                        // outer val
                        XmlElement tblRec = doc.CreateElement(DBTableName);
                        String colName;
                        XmlElement _colName;

                        int colCount = rdr.FieldCount;

                        for (int i = 0; i < colCount; i++)
                        {
                            rdr.Read();
                            colName = rdr[i].ToString();
                            _colName = doc.CreateElement(colName); // Will this return the right 
val?
                            _colName.InnerText = colName;
                            tblRec.AppendChild(_colName);
                        }

                        root.AppendChild(tblRec);
                    } // using (SQLiteDataReader
                } // using (SQLiteCommand
            }
            finally
            {
                xmlOutput = doc.OuterXml;
                doc.Save(String.Format("{0}.xml", DBTableName));
            }
        } // using (SQLiteConnection
    } //  try..catch
    catch (Exception ex)
    {
        String msgInnerExAndStackTrace = String.Format(
            "{0}; Inner Ex: {1}; Stack Trace: {2}", ex.Message, ex.InnerException, 
ex.StackTrace);
        ExceptionLoggingService.Instance.WriteLog(String.Format("From 
HHSDBUtils.GenericSaveDataAndReturnAsXML: {0}", msgInnerExAndStackTrace));
    }
    return xmlOutput;
}

... но теперь, хотя по какой-то причине исключение исчезло, возвращаемое значение val не содержит записи в таблице. Все, что я вижу, это:

<?xml version="1.0"?>
<Command>
<Inventory/>
</Command>

?

ОБНОВЛЕНИЕ 2

Curioser и curiouser: проблема с моим обновлением заключается в том, что у меня был тип глупого гуся (">", где это должно было быть "<"). Но даже с этим исправлено, я получаю исключение:

Date: 2/21/2009 12:54:12 AM
Message: From HHSDBUtils.GenericSaveDataAndReturnAsXML: No current row; Inner Ex: ; Stack 
Trace: at System.Data.SQLite.SQLiteDataReader.CheckValidRow()
   at System.Data.SQLite.SQLiteDataReader.GetValue(Int32 i)
   at System.Data.SQLite.SQLiteDataReader.get_Item(Int32 i)
   at HHS.SQLiteHHSDBUtils.HHS.IHHSDBUtils.GenericSaveDataAndReturnAsXML(String DBTableName)

... и возвращается только XML:

<?xml version="1.0"?>
<Command/>

???

ОБНОВЛЕНИЕ 3

Я изменил код на это:

string IHHSDBUtils.GenericSaveDataAsXML(string DBTableName)
{
    String xmlOutput = String.Empty;
    String qry = String.Format("SELECT * FROM {0}", DBTableName);
    try // catch
    {
        using (SQLiteConnection conn = new SQLiteConnection(HHSUtils.GetDBConnection()))
        {
            conn.Open();
            XmlDocument doc = new XmlDocument();
            XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", null, null);
            doc.AppendChild(dec); // Create the root element
            XmlElement root = doc.CreateElement("Command");
            doc.AppendChild(root);

            // Note that to set the text inside the element,
            // you use .InnerText instead of .Value (which will throw an exception).
            // You use SetAttribute to set attribute
            try
            {
                using (SQLiteCommand cmd = new SQLiteCommand(qry, conn))
                {
                    using (SQLiteDataReader rdr = cmd.ExecuteReader())
                    {
                        //if (!rdr.HasRows) return; <= won't know this yet
                        // outer val
                        XmlElement tblRec = doc.CreateElement(DBTableName);
                        String colName;
                        XmlElement _colName;

                        while (rdr.Read())
                        {
                            int colCount = rdr.FieldCount;

                            for (int i = 0; i < colCount; i++)
                            {
                                colName = rdr[i].ToString();
                                _colName = doc.CreateElement(colName); // Will this return the right val?
                                _colName.InnerText = colName;
                                tblRec.AppendChild(_colName);
                                rdr.Read();
                            }
                            root.AppendChild(tblRec);
                        } // while (rdr.Read())
                    } // using (SQLiteDataReader
                } // using (SQLiteCommand
            }
            finally
            {
                xmlOutput = doc.OuterXml;
                doc.Save(String.Format("{0}.xml", DBTableName));
            }
        } // using (SQLiteConnection
    } //  try..catch
    catch (Exception ex)
    {
        String msgInnerExAndStackTrace = String.Format(
            "{0}; Inner Ex: {1}; Stack Trace: {2}", ex.Message, ex.InnerException, ex.StackTrace);
        ExceptionLoggingService.Instance.WriteLog(String.Format("From HHSDBUtils.GenericSaveDataAndReturnAsXML: {0}", msgInnerExAndStackTrace));
    }
    return xmlOutput;
}

... но все равно получите тот же результат ошибки msg и xml, как описано в обновлении 2.

1 ответ

Решение

Как насчет этого:

    static string GenerateXmlFromTable(string tableName, bool useAttribute)
    {
        XmlDocument document = new XmlDocument();
        XmlDeclaration declaration = document.CreateXmlDeclaration("1.0", null, null);
        document.AppendChild(declaration);

        XmlElement rootElement = document.CreateElement("Command");
        document.AppendChild(rootElement);

        using (SQLiteConnection connection = new SQLiteConnection("Data source=SqlLite.db"))
        {
            connection.Open();

            string query = string.Format("Select * from {0}", tableName);

            using(SQLiteCommand command = new SQLiteCommand(query, connection))
            {
                using(SQLiteDataReader reader = command.ExecuteReader())
                {
                    while(reader.Read())
                    {
                        XmlElement recordElement = document.CreateElement(tableName);
                        rootElement.AppendChild(recordElement);

                        for(int index = 0; index < reader.FieldCount; index++)
                        {
                            if (useAttribute)
                            {
                                recordElement.SetAttribute(reader.GetName(index), reader.GetValue(index).ToString());
                            }
                            else
                            {
                                XmlElement valueElement = document.CreateElement(reader.GetName(index));
                                valueElement.InnerText = reader.GetValue(index).ToString();

                                recordElement.AppendChild(valueElement);
                            }
                        }
                    }
                }
            }
        }

        using(StringWriter stringWriter = new StringWriter(new StringBuilder()))
        using(XmlTextWriter xmlWriter = new XmlTextWriter(stringWriter))
        {
            xmlWriter.Formatting = Formatting.Indented;

            document.Save(xmlWriter);

            return stringWriter.ToString();
        }
    }
Другие вопросы по тегам