10

我想知道是否有一种简单的方法可以读取 Excel 2010 XML?
这个 XML 的结构与我以前阅读的不同。

特别是 ss:index 属性 (ss:Index**="7") 让事情变得更复杂一些

编辑:为了更好地解释:

  • 我有可以在 Excel 中轻松打开的带有 XML 扩展名的文件
  • 我正在寻找一种以编程方式阅读此工作表的方法(例如复制到 DataTable)
  • 注意到这不是我以前工作的常见 XML
  • XML 在开头定义字段,而不是使用 ROW、CELL 和 DATA 标记
  • 令我惊讶的是,当有例如 3 个字段(单元格)但第二个字段没有值时,该字段在 XML 中被“跳过”,但第三个字段有一些额外的“索引”属性,例如:ss:Index**="3 "(这表明即使它在第二个位置右索引也应该是“3”

示例 XML 的片段

      <Row ss:AutoFitHeight="0">
        <Cell><Data ss:Type="String">Johny</Data></Cell>
        <Cell ss:Index="3"><Data ss:Type="String">NY</Data></Cell>
4

6 回答 6

12

好的,我终于从这里找到了解决方案:http: //www.codeproject.com/Articles/32370/Import-Excel-File-to-DataSet#xx

下面的示例代码很少满足我的需要。

public static class XMLtoDataTable {
  private static ColumnType getDefaultType() {
    return new ColumnType(typeof(String));
}

        struct ColumnType {
            public Type type;
            private string name;
            public ColumnType(Type type) { this.type = type; this.name = type.ToString().ToLower(); }
            public object ParseString(string input) {
                if (String.IsNullOrEmpty(input))
                    return DBNull.Value;
                switch (type.ToString()) {
                    case "system.datetime":
                        return DateTime.Parse(input);
                    case "system.decimal":
                        return decimal.Parse(input);
                    case "system.boolean":
                        return bool.Parse(input);
                    default:
                        return input;
                }
            }
        }


    private static ColumnType getType(XmlNode data) {
    string type = null;
    if (data.Attributes["ss:Type"] == null || data.Attributes["ss:Type"].Value == null)
        type = "";
    else
        type = data.Attributes["ss:Type"].Value;

    switch (type) {
        case "DateTime":
            return new ColumnType(typeof(DateTime));
        case "Boolean":
            return new ColumnType(typeof(Boolean));
        case "Number":
            return new ColumnType(typeof(Decimal));
        case "":
            decimal test2;
            if (data == null || String.IsNullOrEmpty(data.InnerText) || decimal.TryParse(data.InnerText, out test2)) {
                return new ColumnType(typeof(Decimal));
            } else {
                return new ColumnType(typeof(String));
            }
        default://"String"
            return new ColumnType(typeof(String));
    }
}

    public static DataSet ImportExcelXML (string fileName, bool hasHeaders, bool autoDetectColumnType) {
        StreamReader sr = new StreamReader( fileName);
        Stream st = (Stream) sr.BaseStream;
        return ImportExcelXML( st, hasHeaders, autoDetectColumnType);
    }

    private static DataSet ImportExcelXML(Stream inputFileStream, bool hasHeaders, bool autoDetectColumnType) {
        XmlDocument doc = new XmlDocument();
        doc.Load(new XmlTextReader(inputFileStream));
        XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);

        nsmgr.AddNamespace("o", "urn:schemas-microsoft-com:office:office");
        nsmgr.AddNamespace("x", "urn:schemas-microsoft-com:office:excel");
        nsmgr.AddNamespace("ss", "urn:schemas-microsoft-com:office:spreadsheet");

        DataSet ds = new DataSet();

        foreach (XmlNode node in 
          doc.DocumentElement.SelectNodes("//ss:Worksheet", nsmgr)) {
            DataTable dt = new DataTable(node.Attributes["ss:Name"].Value);
            ds.Tables.Add(dt);
            XmlNodeList rows = node.SelectNodes("ss:Table/ss:Row", nsmgr);
            if (rows.Count > 0) {

                //*************************
                //Add Columns To Table from header row
                //*************************
                List<ColumnType> columns = new List<ColumnType>();
                int startIndex = 0;
                if (hasHeaders) {
                    foreach (XmlNode data in rows[0].SelectNodes("ss:Cell/ss:Data", nsmgr)) {
                        columns.Add(new ColumnType(typeof(string)));//default to text
                        dt.Columns.Add(data.InnerText, typeof(string));
                    }
                    startIndex++;
                }
                //*************************
                //Update Data-Types of columns if Auto-Detecting
                //*************************
                if (autoDetectColumnType && rows.Count > 0) {
                    XmlNodeList cells = rows[startIndex].SelectNodes("ss:Cell", nsmgr);
                    int actualCellIndex = 0;
                    for (int cellIndex = 0; cellIndex < cells.Count; cellIndex++) {
                        XmlNode cell = cells[cellIndex];
                        if (cell.Attributes["ss:Index"] != null)
                            actualCellIndex = 
                              int.Parse(cell.Attributes["ss:Index"].Value) - 1;

                        ColumnType autoDetectType = 
                          getType(cell.SelectSingleNode("ss:Data", nsmgr));

                        if (actualCellIndex >= dt.Columns.Count) {
                            dt.Columns.Add("Column" + 
                              actualCellIndex.ToString(), autoDetectType.type);
                            columns.Add(autoDetectType);
                        } else {
                            dt.Columns[actualCellIndex].DataType = autoDetectType.type;
                            columns[actualCellIndex] = autoDetectType;
                        }

                        actualCellIndex++;
                    }
                }
                //*************************
                //Load Data
                //*************************
                for (int i = startIndex; i < rows.Count; i++) {
                    DataRow row = dt.NewRow();
                    XmlNodeList cells = rows[i].SelectNodes("ss:Cell", nsmgr);
                    int actualCellIndex = 0;
                    for (int cellIndex = 0; cellIndex < cells.Count; cellIndex++) {
                        XmlNode cell = cells[cellIndex];
                        if (cell.Attributes["ss:Index"] != null)
                            actualCellIndex = int.Parse(cell.Attributes["ss:Index"].Value) - 1;

                        XmlNode data = cell.SelectSingleNode("ss:Data", nsmgr);

                        if (actualCellIndex >= dt.Columns.Count) {
                            for (int ii = dt.Columns.Count; ii < actualCellIndex; ii++) {
                                dt.Columns.Add("Column" + actualCellIndex.ToString(), typeof(string));columns.Add(getDefaultType());
                            } // ii
                            ColumnType autoDetectType = 
                               getType(cell.SelectSingleNode("ss:Data", nsmgr));
                            dt.Columns.Add("Column" + actualCellIndex.ToString(), 
                                           typeof(string));
                            columns.Add(autoDetectType);
                        }
                        if (data != null)
                            row[actualCellIndex] = data.InnerText;

                        actualCellIndex++;
                    }

                    dt.Rows.Add(row);
                }
            }
        }
        return ds;
    }


}
于 2012-10-15T16:16:02.720 回答
3

即使没有 coumn type 它也可以正常工作。谢谢 !!!

有无柱类型的样本:

    private static DataSet ImportExcelXML(Stream inputFileStream, bool hasHeaders)
{
    XmlDocument doc = new XmlDocument();
    doc.Load(new XmlTextReader(inputFileStream));
    XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);

    nsmgr.AddNamespace("o", "urn:schemas-microsoft-com:office:office");
    nsmgr.AddNamespace("x", "urn:schemas-microsoft-com:office:excel");
    nsmgr.AddNamespace("ss", "urn:schemas-microsoft-com:office:spreadsheet");

    DataSet ds = new DataSet();

    foreach (XmlNode node in
      doc.DocumentElement.SelectNodes("//ss:Worksheet", nsmgr))
    {
        DataTable dt = new DataTable(node.Attributes["ss:Name"].Value);
        ds.Tables.Add(dt);
        XmlNodeList rows = node.SelectNodes("ss:Table/ss:Row", nsmgr);
        if (rows.Count > 0)
        {

            //*************************
            //Add Columns To Table from header row
            //*************************
            List<ColumnType> columns = new List<ColumnType>();
            int startIndex = 0;
            if (hasHeaders)
            {
                foreach (XmlNode data in rows[0].SelectNodes("ss:Cell/ss:Data", nsmgr))
                {
                    columns.Add(new ColumnType(typeof(string)));//default to text
                    dt.Columns.Add(data.InnerText, typeof(string));
                }
                startIndex++;
            }
            //*************************
            //Update Data-Types of columns if Auto-Detecting
            //*************************
            if (rows.Count > 0)
            {
                XmlNodeList cells = rows[startIndex].SelectNodes("ss:Cell", nsmgr);
                int actualCellIndex = 0;
                for (int cellIndex = 0; cellIndex < cells.Count; cellIndex++)
                {
                    XmlNode cell = cells[cellIndex];
                    if (cell.Attributes["ss:Index"] != null)
                        actualCellIndex =
                          int.Parse(cell.Attributes["ss:Index"].Value) - 1;

                    //ColumnType autoDetectType =
                    //  getType(cell.SelectSingleNode("ss:Data", nsmgr));

                    if (actualCellIndex >= dt.Columns.Count)
                    {
                        //dt.Columns.Add("Column" +
                        //  actualCellIndex.ToString(), autoDetectType.type);
                        dt.Columns.Add("Column" + actualCellIndex.ToString());
                        //columns.Add(autoDetectType);
                    }
                    else
                    {
                        //dt.Columns[actualCellIndex].DataType = autoDetectType.type;
                        //columns[actualCellIndex] = autoDetectType;
                    }

                    actualCellIndex++;
                }
            }
            //*************************
            //Load Data
            //*************************
            for (int i = startIndex; i < rows.Count; i++)
            {
                DataRow row = dt.NewRow();
                XmlNodeList cells = rows[i].SelectNodes("ss:Cell", nsmgr);
                int actualCellIndex = 0;
                for (int cellIndex = 0; cellIndex < cells.Count; cellIndex++)
                {
                    XmlNode cell = cells[cellIndex];
                    if (cell.Attributes["ss:Index"] != null)
                        actualCellIndex = int.Parse(cell.Attributes["ss:Index"].Value) - 1;

                    XmlNode data = cell.SelectSingleNode("ss:Data", nsmgr);

                    if (actualCellIndex >= dt.Columns.Count)
                    {
                        for (int ii = dt.Columns.Count; ii < actualCellIndex; ii++)
                        {
                            //dt.Columns.Add("Column" + actualCellIndex.ToString(), typeof(string)); columns.Add(getDefaultType());
                            dt.Columns.Add("Column" + actualCellIndex.ToString());
                            //columns.Add(getDefaultType());
                        } // ii
                        //ColumnType autoDetectType = getType(cell.SelectSingleNode("ss:Data", nsmgr));
                        dt.Columns.Add("Column" + actualCellIndex.ToString(),
                                       typeof(string));
                        // columns.Add(autoDetectType);
                    }
                    if (data != null)
                        row[actualCellIndex] = data.InnerText;

                    actualCellIndex++;
                }

                dt.Rows.Add(row);
            }
        }
    }
    return ds;
}
于 2014-04-23T08:47:08.900 回答
1

首先尝试官方 API(Microsoft Open XML SDK)。

于 2012-10-15T14:28:40.033 回答
1

您可以尝试使用此代码

    var textReader = new XmlTextReader("...\\YourFile.xml");
    // Read until end of file
    while (textReader.Read())
    {
        XmlNodeType nType = textReader.NodeType;
        // If node type us a declaration
        if (nType == XmlNodeType.XmlDeclaration)
        {
            Console.WriteLine("Declaration:" + textReader.Name.ToString());
        }
        // if node type is a comment
        if (nType == XmlNodeType.Comment)
        {
            Console.WriteLine("Comment:" + textReader.Name.ToString());
        }
        // if node type us an attribute
        if (nType == XmlNodeType.Attribute)
        {
            Console.WriteLine("Attribute:" + textReader.Name.ToString());
        }
        // if node type is an element
        if (nType == XmlNodeType.Element)
        {
            Console.WriteLine("Element:" + textReader.Name.ToString());
        }
        // if node type is an entity\
        if (nType == XmlNodeType.Entity)
        {
            Console.WriteLine("Entity:" + textReader.Name.ToString());
        }
        // if node type is a Process Instruction
        if (nType == XmlNodeType.Entity)
        {
            Console.WriteLine("Entity:" + textReader.Name.ToString());
        }
        // if node type a document
        if (nType == XmlNodeType.DocumentType)
        {
            Console.WriteLine("Document:" + textReader.Name.ToString());
        }
        // if node type is white space
        if (nType == XmlNodeType.Whitespace)
        {
            Console.WriteLine("WhiteSpace:" + textReader.Name.ToString());
        }
    }
于 2012-10-15T14:29:54.440 回答
1
public static class XMLtoDataTable
{
    private static ColumnType getDefaultType()
    {
        return new ColumnType(typeof(String));
    }

    struct ColumnType
    {
        public Type type;
        private string name;
        public ColumnType(Type type) { this.type = type; this.name = type.ToString().ToLower(); }
        public object ParseString(string input)
        {
            if (String.IsNullOrEmpty(input))
                return DBNull.Value;
            switch (type.ToString())
            {
                case "system.datetime":
                    return DateTime.Parse(input);
                case "system.decimal":
                    return decimal.Parse(input);
                case "system.boolean":
                    return bool.Parse(input);
                default:
                    return input;
            }
        }
    }


    private static ColumnType getType(XmlNode data)
    {
        string type = null;
        if (data.Attributes["ss:Type"] == null || data.Attributes["ss:Type"].Value == null)
            type = "";
        else
            type = data.Attributes["ss:Type"].Value;

        switch (type)
        {
            case "DateTime":
                return new ColumnType(typeof(DateTime));
            case "Boolean":
                return new ColumnType(typeof(Boolean));
            case "Number":
                return new ColumnType(typeof(Decimal));
            case "":
                decimal test2;
                if (data == null || String.IsNullOrEmpty(data.InnerText) || decimal.TryParse(data.InnerText, out test2))
                {
                    return new ColumnType(typeof(Decimal));
                }
                else
                {
                    return new ColumnType(typeof(String));
                }
            default://"String"
                return new ColumnType(typeof(String));
        }
    }

    public static DataSet ImportExcelXML(string fileName, bool hasHeaders, bool autoDetectColumnType)
    {
        StreamReader sr = new StreamReader(fileName);
        Stream st = (Stream)sr.BaseStream;
        return ImportExcelXML(st, hasHeaders, autoDetectColumnType);
    }

    private static DataSet ImportExcelXML(Stream inputFileStream, bool hasHeaders, bool autoDetectColumnType)
    {
        XmlDocument doc = new XmlDocument();
        doc.Load(new XmlTextReader(inputFileStream));
        XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);

        nsmgr.AddNamespace("o", "urn:schemas-microsoft-com:office:office");
        nsmgr.AddNamespace("x", "urn:schemas-microsoft-com:office:excel");
        nsmgr.AddNamespace("ss", "urn:schemas-microsoft-com:office:spreadsheet");

        DataSet ds = new DataSet();

        foreach (XmlNode node in
          doc.DocumentElement.SelectNodes("//ss:Worksheet", nsmgr))
        {
            DataTable dt = new DataTable(node.Attributes["ss:Name"].Value);
            ds.Tables.Add(dt);
            XmlNodeList rows = node.SelectNodes("ss:Table/ss:Row", nsmgr);
            if (rows.Count > 0)
            {

                //*************************
                //Add Columns To Table from header row
                //*************************
                List<ColumnType> columns = new List<ColumnType>();
                int startIndex = 0;
                if (hasHeaders)
                {
                    foreach (XmlNode data in rows[0].SelectNodes("ss:Cell/ss:Data", nsmgr))
                    {
                        columns.Add(new ColumnType(typeof(string)));//default to text
                        dt.Columns.Add(data.InnerText, typeof(string));
                    }
                    startIndex++;
                }
                //*************************
                //Update Data-Types of columns if Auto-Detecting
                //*************************
                if (autoDetectColumnType && rows.Count > 0)
                {
                    XmlNodeList cells = rows[startIndex].SelectNodes("ss:Cell", nsmgr);
                    int actualCellIndex = 0;
                    for (int cellIndex = 0; cellIndex < cells.Count; cellIndex++)
                    {
                        XmlNode cell = cells[cellIndex];
                        if (cell.Attributes["ss:Index"] != null)
                            actualCellIndex =
                              int.Parse(cell.Attributes["ss:Index"].Value) - 1;

                        ColumnType autoDetectType =
                          getType(cell.SelectSingleNode("ss:Data", nsmgr));

                        if (actualCellIndex >= dt.Columns.Count)
                        {
                            dt.Columns.Add("Column" +
                              actualCellIndex.ToString(), autoDetectType.type);
                            columns.Add(autoDetectType);
                        }
                        else
                        {
                            dt.Columns[actualCellIndex].DataType = autoDetectType.type;
                            columns[actualCellIndex] = autoDetectType;
                        }

                        actualCellIndex++;
                    }
                }
                //*************************
                //Load Data
                //*************************
                for (int i = startIndex; i < rows.Count; i++)
                {
                    DataRow row = dt.NewRow();
                    XmlNodeList cells = rows[i].SelectNodes("ss:Cell", nsmgr);
                    int actualCellIndex = 0;
                    for (int cellIndex = 0; cellIndex < cells.Count; cellIndex++)
                    {
                        XmlNode cell = cells[cellIndex];
                        if (cell.Attributes["ss:Index"] != null)
                            actualCellIndex = int.Parse(cell.Attributes["ss:Index"].Value) - 1;

                        XmlNode data = cell.SelectSingleNode("ss:Data", nsmgr);

                        if (actualCellIndex >= dt.Columns.Count)
                        {
                            for (int ii = dt.Columns.Count; ii < actualCellIndex; ii++)
                            {
                                dt.Columns.Add("Column" + actualCellIndex.ToString(), typeof(string)); columns.Add(getDefaultType());
                            } // ii
                            ColumnType autoDetectType =
                               getType(cell.SelectSingleNode("ss:Data", nsmgr));
                            dt.Columns.Add("Column" + actualCellIndex.ToString(),
                                           typeof(string));
                            columns.Add(autoDetectType);
                        }
                        if (data != null)
                            row[actualCellIndex] = data.InnerText;

                        actualCellIndex++;
                    }

                    dt.Rows.Add(row);
                }
            }
        }
        return ds;
    }


}
于 2014-04-23T10:40:12.090 回答
0
 public class ExcelXMLtoDataTable
{
    private static ColumnType getDefaultType()
    {
        return new ColumnType(typeof(String));
    }

    struct ColumnType
    {
        public Type type;
        private string name;

        public ColumnType(Type type)
        {
            this.type = type; this.name = type.ToString().ToLower();

        }
        public object ParseString(string input)
        {
            if (String.IsNullOrEmpty(input))
                return DBNull.Value;
            switch (type.ToString())
            {
                case "system.datetime":
                    return DateTime.Parse(input);
                case "system.decimal":
                    return decimal.Parse(input);
                case "system.boolean":
                    return bool.Parse(input);
                default:
                    return input;
            }
        }
    }


    private static ColumnType getType(XmlNode data)
    {
        string type = null;
        //if (data == null)
        //    type = "";
        // else 
        if (data.Attributes["ss:Type"] == null || data.Attributes["ss:Type"].Value == "")
            type = "";
        else
            type = data.Attributes["ss:Type"].Value;

        switch (type)
        {
            case "DateTime":
                return new ColumnType(typeof(DateTime));
            case "Boolean":
                return new ColumnType(typeof(Boolean));
            case "Number":
                return new ColumnType(typeof(Decimal));
            case "":
                decimal test2;
                if (data == null || String.IsNullOrEmpty(data.InnerText) || decimal.TryParse(data.InnerText, out test2))
                {
                    return new ColumnType(typeof(Decimal));
                    return new ColumnType(typeof(String));
                }
                else
                {
                    return new ColumnType(typeof(String));
                }
            default://"String"
                return new ColumnType(typeof(String));
        }
    }

    public static DataSet ImportExcelXML(string fileName, bool hasHeaders, bool autoDetectColumnType)
    {
        StreamReader sr = new StreamReader(fileName);
        Stream st = (Stream)sr.BaseStream;
        return ImportExcelXML(st, hasHeaders, autoDetectColumnType);
    }
    private static DataSet ImportExcelXML(Stream inputFileStream, bool hasHeaders, bool autoDetectColumnType)
    {
        XmlDocument doc = new XmlDocument();
        doc.Load(new XmlTextReader(inputFileStream));
        XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);

        nsmgr.AddNamespace("o", "urn:schemas-microsoft-com:office:office");
        nsmgr.AddNamespace("x", "urn:schemas-microsoft-com:office:excel");
        nsmgr.AddNamespace("ss", "urn:schemas-microsoft-com:office:spreadsheet");

        DataSet ds = new DataSet();

        foreach (XmlNode node in
          doc.DocumentElement.SelectNodes("//ss:Worksheet", nsmgr))
        {
            DataTable dt = new DataTable(node.Attributes["ss:Name"].Value);
            ds.Tables.Add(dt);
            XmlNodeList rows = node.SelectNodes("ss:Table/ss:Row", nsmgr);
            if (rows.Count > 0)
            {

                //*************************
                //Add Columns To Table from header row
                //*************************
                List<ColumnType> columns = new List<ColumnType>();
                int startIndex = 0;
                if (hasHeaders)
                {
                    foreach (XmlNode data in rows[0].SelectNodes("ss:Cell/ss:Data", nsmgr))
                    {
                        columns.Add(new ColumnType(typeof(string)));//default to text
                        dt.Columns.Add(data.InnerText, typeof(string));
                    }
                    startIndex++;
                }
                //*************************
                //Update Data-Types of columns if Auto-Detecting
                //*************************
                if (autoDetectColumnType && rows.Count > 0)
                {
                    XmlNodeList cells = rows[startIndex].SelectNodes("ss:Cell", nsmgr);
                    int actualCellIndex = 0;
                    for (int cellIndex = 0; cellIndex < cells.Count; cellIndex++)
                    {
                        XmlNode cell = cells[cellIndex];
                        if (cell.Attributes["ss:Index"] != null)
                            actualCellIndex =
                              int.Parse(cell.Attributes["ss:Index"].Value) - 1;

                        //ColumnType autoDetectType =
                        //  getType(cell.SelectSingleNode("ss:Data", nsmgr));

                        if (actualCellIndex >= dt.Columns.Count)
                        {
                            //dt.Columns.Add("Column" +
                            //  actualCellIndex.ToString(), autoDetectType.type);
                            dt.Columns.Add("Column" + actualCellIndex.ToString());
                            //columns.Add(autoDetectType);
                        }
                        else
                        {
                            //dt.Columns[actualCellIndex].DataType = autoDetectType.type;
                            //columns[actualCellIndex] = autoDetectType;
                        }

                        actualCellIndex++;
                    }
                }
                //*************************
                //Load Data
                //*************************
                for (int i = startIndex; i < rows.Count; i++)
                {
                    DataRow row = dt.NewRow();
                    XmlNodeList cells = rows[i].SelectNodes("ss:Cell", nsmgr);
                    int actualCellIndex = 0;
                    for (int cellIndex = 0; cellIndex < cells.Count; cellIndex++)
                    {
                        XmlNode cell = cells[cellIndex];
                        if (cell.Attributes["ss:Index"] != null)
                            actualCellIndex = int.Parse(cell.Attributes["ss:Index"].Value) - 1;

                        XmlNode data = cell.SelectSingleNode("ss:Data", nsmgr);

                        if (actualCellIndex >= dt.Columns.Count)
                        {
                            for (int ii = dt.Columns.Count; ii < actualCellIndex; ii++)
                            {
                                //dt.Columns.Add("Column" + actualCellIndex.ToString(), typeof(string)); columns.Add(getDefaultType());
                                dt.Columns.Add("Column" + actualCellIndex.ToString());
                                //columns.Add(getDefaultType());
                            } // ii
                            //ColumnType autoDetectType = getType(cell.SelectSingleNode("ss:Data", nsmgr));
                            dt.Columns.Add("Column" + actualCellIndex.ToString(),
                                           typeof(string));
                            // columns.Add(autoDetectType);
                        }
                        if (data != null)
                            row[actualCellIndex] = data.InnerText;

                        actualCellIndex++;
                    }

                    dt.Rows.Add(row);
                }
            }
        }
        return ds;
    }

}
于 2014-04-23T10:36:36.397 回答