Pregunta

Aquí está el trato. Tengo un documento XML con muchos registros. Algo como esto:

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>");

También hay un archivo de esquema XSD. Me gustaría extraer datos de este archivo e insertar estos registros en una tabla de base de datos. Primero, por supuesto, me gustaría validar cada registro de pedido. Por ejemplo, si hay 5 órdenes en el archivo y 2 de ellas fallan en la validación, me gustaría insertar las 3 que pasaron la validación en la db y dejaron las otras 2. Puede haber miles de registros en un archivo xml. ¿Cuál sería el mejor enfoque aquí? ¿Y cómo iría la validación para esto, ya que necesito descartar los registros fallidos y usar solo los que pasaron la validación? En este momento estoy usando XmlReaderSettings para validar los registros de documentos XML. Debería extraer estos registros en otro archivo XML o en un conjunto de datos o en un objeto personalizado antes de insertarlo en una base de datos. Estoy usando .Net 3.5. Cualquier código o enlace es bienvenido.

¿Fue útil?

Solución

Tienes un par de opciones:

  1. XmlDataDocument o XmlDocument . La desventaja de este enfoque es que los datos se almacenarán en caché en la memoria, lo cual es malo si tiene mucha información. Por otro lado, obtiene buenas facilidades de consulta en memoria con DataSet. XmlDocument requiere que uses consultas XPath para trabajar con los datos, mientras que XmlDataDocument te brinda una experiencia más parecida a la funcionalidad DataSet.

  2. XmlReader . Este es un enfoque bueno y rápido porque los datos no se almacenan en caché; Lo lees en un momento a la vez como una secuencia. Se mueve de un elemento a otro y consulta información sobre ese elemento en su aplicación para decidir qué hacer con él. Esto significa que mantendrá en la memoria de su aplicación el nivel del árbol en el que se encuentra, pero con una estructura de archivos XML simple como la suya, esto debería ser muy simple.

Recomiendo la opción 2 en tu caso. Debe escalar bien en términos de uso de memoria y debe proporcionar la implementación más sencilla para procesar un archivo.

Otros consejos

Si los datos se asignan de manera bastante clara a un modelo de objeto, podría intentar usar xsd.exe para generar algunas clases desde el .xsd y procesar las clases en el DAL de su elección. El problema es que si el volumen es alto (mencionas miles de registros), lo más probable es que tengas un lote de viajes de ida y vuelta.

Otra opción podría ser pasar los datos " tal como está " a través de la base de datos y use SQL / XML para procesar los datos en TSQL, presumiblemente como un procedimiento almacenado que acepta un parámetro de tipo xml (SQL Server 2005, etc.).

Estoy de acuerdo con la idea de que deberías usar un XmlReader, pero pensé que intentaría algo un poco diferente.

Básicamente, primero estoy validando todo el XDocument, luego, si hay errores, los enumero a través de las órdenes y los coloco según sea necesario. No es bonito, pero quizás te dé algunas ideas.

        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();
        }

En lugar de las expresiones lambda, podrías usar una función común, pero simplemente tiré esto juntos. Además, podría crear dos XDocuments en lugar de incluir los elementos del pedido en una lista. Estoy seguro de que también hay un montón de otros problemas aquí, pero quizás esto provoque algo.

Mucho de eso depende de lo que " validación " Significa en tu escenario. Supongo que, dado que está utilizando un .xsd, ya está validando que los datos son sintácticamente correctos. Entonces, ¿la validación probablemente significa que llamará a otros servicios o procedimientos para determinar si una orden es válida?

Es posible que desee ver los Servicios de Integración del Servidor SQL. La tarea XML en SSIS le permite hacer cosas como consultas XPath, fusionar, probablemente cualquier cosa y todo lo que necesita hacer con ese documento. También puede usar ese hacer para toda su validación inicial con el archivo de esquema también.

La opción de Marc de pasar esos datos a un procedimiento almacenado también podría funcionar en este escenario, pero SSIS (o incluso DTS, pero abandonará demasiado en relación con XML para que sea una buena opción) Deje que orquesten visualmente todo este trabajo. Además, facilitará que estas cosas se agoten, por lo que debería terminar con una solución mucho más escalable.

Por validación me refiero a validar cada nodo. Los nodos que tienen al menos un error deben insertarse en un nuevo documento xml. Básicamente al final debería tener 2 documentos xml. Uno que contiene los nodos exitosos y el otro que contiene los nodos de falla. ¿De alguna manera puedo lograr eso? Estoy usando LINQ.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top