代码之家  ›  专栏  ›  技术社区  ›  Malik Daud Ahmad Khokhar

逐条验证XML记录并将其提取到数据库中

  •  1
  • Malik Daud Ahmad Khokhar  · 技术社区  · 17 年前

    成交了。我有一个有很多记录的XML文档。像这样:

    print("<?xml version="1.0" encoding="utf-8" ?>
          <Orders>
           <Order>
             <Phone>1254</Phone>
             <City>City1</City>
          <State>State</State>
          </Order>
          <Order>
             <Phone>98764321</Phone>
             <City>City2</City>
            <State>State2</State>
          </Order>  
         </Orders>");
    

    还有一个XSD模式文件。我想从这个文件中提取数据,并将这些记录插入到数据库表中。首先,我想验证每个订单记录。例如,如果文件中有5个订单,其中2个未通过验证,我想将通过验证的3个订单插入到数据库中,剩下2个订单。一个XML文件中可以有数千条记录。这里最好的方法是什么?既然我需要丢弃失败的记录,只使用通过验证的记录,那么验证将如何进行呢?目前我正在使用 XmlReaders设置 验证XML文档记录。在插入数据库之前,是否应该将这些记录提取到另一个XML文件、数据集或自定义对象中?我用的是.NET 3.5。欢迎使用任何代码或链接。

    5 回复  |  直到 17 年前
        1
  •  0
  •   Neil Barnwell    17 年前

    您有几个选择:

    1. XmlDataDocument XmlDocument . 这种方法的缺点是数据将被缓存在内存中,如果您有大量的数据,这是很糟糕的。另一方面,您可以使用数据集获得良好的内存查询功能。xmldocument要求使用xpath查询处理数据,而xmldatadocument则提供了更类似于数据集功能的体验。

    2. XmlReader . 这是一种好的、快速的方法,因为数据没有被缓存;您可以将其作为流一次读取一点。您可以从一个元素移动到下一个元素,并在应用程序中查询关于该元素的信息,以决定如何处理它。这确实意味着您要在应用程序的内存中维护您所处的树级别,但是使用像您这样的简单XML文件结构,这应该非常简单。

    我建议在你的情况下选择2。它应该在内存使用方面具有良好的伸缩性,并且应该为处理文件提供最简单的实现。

        2
  •  1
  •   Marc Gravell    17 年前

    如果数据相当清晰地映射到对象模型,您可以尝试使用xsd.exe从.xsd生成一些类,并将这些类处理到您选择的DAL中。问题是,如果卷很高(您提到了数千条记录),则很可能 许多 往返旅行。

    另一种选择可能是将数据“按原样”传递到数据库,并使用SQL/XML处理TSQL中的数据-可能是接受XML类型参数(SQL Server 2005等)的存储过程。

        3
  •  1
  •   Richard Morgan    17 年前

    我同意你应该使用一个XML阅读器的想法,但我想我会尝试一些不同的方法。

    基本上,我首先验证整个xdocument,然后如果有错误,我将枚举整个订单,并根据需要将它们存储起来。它不漂亮,但也许会给你一些建议。

            XDocument doc = XDocument.Load("sample.xml");
            XmlSchemaSet schemas = new XmlSchemaSet();
            schemas.Add("", "sample.xsd");
    
            bool errors = false;
            doc.Validate(schemas, (sender, e) =>
            {
                errors = true;
            });
    
            List<XElement> good = new List<XElement>();
            List<XElement> bad = new List<XElement>();
            var orders = doc.Descendants("Order");
            if (errors)
            {
                foreach (var order in orders)
                {
                    errors = false;
                    order.Validate(order.GetSchemaInfo().SchemaElement, schemas, (sender, e) =>
                    {
                        errors = true;
                    });
    
                    if (errors)
                        bad.Add(order);
                    else
                        good.Add(order);
                }
            }
            else
            {
                good = orders.ToList();
            }
    

    您可以使用一个公共函数来代替lambda表达式,但我只是把它放在一起。另外,您可以构建两个xdocument,而不是将order元素推送到一个列表中。我相信这里也有很多其他的问题,但也许这会引发一些问题。

        4
  •  0
  •   joshua.ewer    17 年前

    这很大程度上取决于“验证”在您的场景中的含义。我假设,因为您使用的是.xsd,所以您已经在验证数据的语法是否正确。 所以,验证可能意味着您将调用其他服务或过程来确定订单是否有效?

    您可能需要查看SQL Server集成服务。SSIS中的XML任务允许您执行诸如XPath查询、合并之类的操作,可能还可以执行与该文档相关的所有操作。您也可以使用这个方法对模式文件进行所有的前期验证。

    Marc将数据传递到存储过程的选项在这种情况下也可能有效,但是ssis(或者,甚至是dts,但是您将放弃太多与XML相关的内容,使其成为一个不错的选项)将使您在视觉上协调所有这些工作。另外,它将使这些东西更容易耗尽流程,因此您最终应该得到一个更具可扩展性的解决方案。

        5
  •  0
  •   Malik Daud Ahmad Khokhar    17 年前

    通过验证,我的意思是验证每个节点。至少有一个错误的节点需要插入到新的XML文档中。最后,我应该有两个XML文档。一个包含成功节点,另一个包含失败节点。我能做到吗?我用的是LINQ。