C# XML 解析问题

Posted

技术标签:

【中文标题】C# XML 解析问题【英文标题】:C# XML parsing issue 【发布时间】:2012-10-12 23:12:03 【问题描述】:

我正在尝试导入一个包含大量特殊字符的大型 xml 文件,这些特殊字符不断在我的应用程序中抛出错误。在导致令牌错误之前,我通过 XML 文件中的大约 76 条记录。 "解析查询时出错。[Token line number = 1,Token line offset = 725,Token in error = S]"

我已经把我的代码放在下面了。

public void ReadXMLIntoDB()
        
            OpenFileDialog ofd;
            ofd = new OpenFileDialog();
            ofd.Filter = "Xml Files|*.xml|AllFiles|*.*";
            ofd.ShowDialog();

            StreamReader sr = new StreamReader(ofd.FileName);
            XmlTextReader xr = new XmlTextReader(sr);
            int iNumRows = 0;
            while (xr.ReadToFollowing("row") != false)
            
                string sFacName, sFacID, sAddress, sCity, sState, sZip, sOwnerID, sOwnerName, sStreetNum, sStreetName, sStreetType, sPostDirectional, sPhone, sProgramCat, sProgramCatDes, sInspectionDate, sInspectionType, sInspectionDes, sSerialNum, sActionCode, sActionDes, sResultCode, sResultDes, sViolationCode, sViolationDes, sInspectionMemo;
                xr.ReadToFollowing("value");
                sFacName = xr.ReadInnerXml();

                xr.ReadToFollowing("value");
                sFacID = xr.ReadInnerXml();

                xr.ReadToFollowing("value");
                sAddress = xr.ReadInnerXml();

                xr.ReadToFollowing("value");
                sCity = xr.ReadInnerXml();

                xr.ReadToFollowing("value");
                sState = xr.ReadInnerXml();

                xr.ReadToFollowing("value");
                sZip = xr.ReadInnerXml();

                xr.ReadToFollowing("value");
                sOwnerID = xr.ReadInnerXml();

                xr.ReadToFollowing("value");
                sOwnerName = xr.ReadInnerXml();

                xr.ReadToFollowing("value");
                sStreetNum = xr.ReadInnerXml();

                xr.ReadToFollowing("value");
                sStreetName = xr.ReadInnerXml();

                xr.ReadToFollowing("value");
                sStreetType = xr.ReadInnerXml();

                xr.ReadToFollowing("value");
                sPostDirectional = xr.ReadInnerXml();

                xr.ReadToFollowing("value");
                sPhone = xr.ReadInnerXml();

                xr.ReadToFollowing("value");
                sProgramCat = xr.ReadInnerXml();

                xr.ReadToFollowing("value");
                sProgramCatDes = xr.ReadInnerXml();

                xr.ReadToFollowing("value");
                sInspectionDate = xr.ReadInnerXml();

                xr.ReadToFollowing("value");
                sInspectionType = xr.ReadInnerXml();

                xr.ReadToFollowing("value");
                sInspectionDes = xr.ReadInnerXml();

                xr.ReadToFollowing("value");
                sSerialNum = xr.ReadInnerXml();

                xr.ReadToFollowing("value");
                sActionCode = xr.ReadInnerXml();

                xr.ReadToFollowing("value");
                sActionDes = xr.ReadInnerXml();

                xr.ReadToFollowing("value");
                sResultCode = xr.ReadInnerXml();

                xr.ReadToFollowing("value");
                sResultDes = xr.ReadInnerXml();

                xr.ReadToFollowing("value");
                sViolationCode = xr.ReadInnerXml();

                xr.ReadToFollowing("value");
                sViolationDes = xr.ReadInnerXml();

                xr.ReadToFollowing("value");
                sInspectionMemo = xr.ReadInnerXml();
                Regex.Replace(sInspectionMemo, @"[^\w\&#.@-]", "");

                SqlCeConnection con;
                SqlCeCommand cmd;
                string cstr, sql;

                cstr = @"Data Source=|DataDirectory|\foodDB.sdf";
                sql = String.Format("Insert Into food(FacilityName,FacilityID,SiteAddress,City,State,ZipCode,OwnerID,OwnerName,StreetNumber,StreetName,StreetType,PostDirectional,Phone,ProgramCategory,ProgramCategoryDescription,InspectionDate,InspectionType,InspectionDescription,SerialNumber,ActionCode,ActionDescription,ResultCode,ResultDescription,ViolationCode,ViolationDescription,InspectionMemo) values ('0','1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','23','24','25')", sFacName, sFacID, sAddress, sCity, sState, sZip, sOwnerID, sOwnerName, sStreetNum, sStreetName, sStreetType, sPostDirectional, sPhone, sProgramCat, sProgramCatDes, sInspectionDate, sInspectionType, sInspectionDes, sSerialNum, sActionCode, sActionDes, sResultCode, sResultDes, sViolationCode, sViolationDes, sInspectionMemo);
                con = new SqlCeConnection(cstr);
                cmd = new SqlCeCommand(sql, con);
                con.Open();
                cmd.ExecuteNonQuery();
                con.Close();

                ++iNumRows;

                Action ac = delegate()
                
                    txrows.Text = iNumRows.ToString();
                ;
                Dispatcher.BeginInvoke(ac);
            

        

        private void Button_Click_1(object sender, RoutedEventArgs e)
        
            Thread t = new Thread(ReadXMLIntoDB);
            t.Start();
        

据我所知,我可以在该记录中看到可能导致错误的唯一明显的事情是 a ' 应该在哪里。有人可以帮帮我吗?

【问题讨论】:

如果您没有可以跳转到行偏移量 725 的文本编辑器,请通过 XML 格式化程序运行您的 XML 以添加换行符和缩进。然后你会得到一个错误的行号和偏移量,它会更容易查看。 一些基本的调试建议。您在解析 xml 时遇到问题。所以摆脱一切。硬编码文件名,删除线程,并删除数据库内容。我的猜测是,每次运行此程序时,您都必须手动选择文件然后运行它,然后稍等片刻,等等。这只是在浪费时间进行故障排除。并且线程只会使调试变得更加困难。如果没有线程,Visual Studio 应该会在错误时自动中断。您可以随时将其添加回来。 不幸的是,我拥有的 xml 文件来自城市网站,大小约为 110Mb...我试图通过在线格式化程序运行它,但恐怕它也需要长。任何您可以指点我下载以在本地运行的免费格式化程序将不胜感激。 试试记事本++。有一些插件可以让你做到这一点。 ***.com/questions/3961217/… 向我们展示导致问题的 XML。编辑您的问题并将错误两侧的几行 XML 粘贴到问题中。这里有人可能会发现一个问题。如果数据包含个人信息,请通过将 a-z 替换为 * 来编辑内容。不要修改 XML 标记或属性名称。另外,请留意内容中的符号,例如“>”。如果内容中的“>”未正确转义,则可能会使解析 XML“非常困难”。 【参考方案1】:

您的 xml 文档可能无效。无论如何,您可以设置将在第 76 次迭代时发生的断点并检查错误。

pS:在 while 语句的某处设置断点。右键单击断点并选择 HitCount。

【讨论】:

我没有意识到你可以做到这一点。我现在正在尝试。谢谢! 好的,所以它实际上是 77,但是当我在断点暂停进度后单击继续时,我在解析之前的查询时遇到同样的错误。我对编程和使用 XML 非常陌生,所以我很感激你能给我的任何帮助。 不要按继续,按 F11。当您收到异常时,请单击View details 超链接并查找Inner exception。可能有关于此错误的更详细信息。 您说您有一个包含大量特殊字符的大型 xml。尝试更改XmlTextReader的编码***.com/questions/961699/… 我试过没有用。也许一些睡眠和一双新的眼睛会帮助我明天完成它。感谢您的帮助!【参考方案2】:

我不久前用 C# 写了一个XML with XSD validator,它可以很容易地适应跳过 XSD 并只检查 XML 是否至少格式正确。如果您有 XSD 架构,还可以检查 XML 是否有效。

Well formed XML 遵守一些 XML 规则Valid XML 是格式良好的 XML,也满足模式(XSD 可用于制定这样的模式)

该工具将向您显示 XML 文档的格式不正确或无效的位置。

让这个工具工作的最简单方法就是download the whole bo-library source code tree,然后将bo-Library.sln 解决方案加载到Visual Studio 中,选择ValidateXmlWithXsd.csproj 并从那里开始。

【讨论】:

以上是关于C# XML 解析问题的主要内容,如果未能解决你的问题,请参考以下文章

C# 解析 XML 文件

使用 C# 解析 XML 文件

如何在 C# 中配置 XML 解析器以禁用外部实体解析

如何在 C# 中解析非常大的 XML 文件? [复制]

在 C# 中解析 XML 数据并显示到 ListBox

如何在 C# 中读取和解析 XML 文件?