none
Leer fichero XML en DataTable RRS feed

  • Pregunta

  • Hola:

    Tengo un fichero como éste:

    <?xml version="1.0" encoding="windows-1252"?> <info> <fecha20120101> <codigo1 prop1="" pProp2="" Prop3="" Nombre="Nombre1" /> <codigo2 prop1="2" prop2="1" prop3="4" Nombre="Nombre2" /> <codigo33 prop1="2" prop2="2" prop3="5" Nombre="Nombre33" /> <codigo4 prop1="2" prop2="1" prop3="8" Nombre="Nombre4" /> <codigo45 prop1="2" prop2="2" prop3="3" Nombre="Nombre45" /> <codigo99 prop1="2" prop2="1" prop3="9" Nombre="Nombre99" /> <codigo15 prop1="2" prop2="3" prop3="5" Nombre="Nombre15" /> </fecha20120101> <fecha20120201> <codigo250 prop1="3" prop2="1" prop3="100" Nombre="Nombre250" /> </fecha20120201> <fecha20120301> <codigo250 prop1="3" prop2="2" prop3="100" Nombre="Nombre250" /> </fecha20120301> </info>

    Y quiero leer los registros <codigo(nn) ...> con sus propiedades y nombres en un datatable, cada registro tiene que tener también la fecha a la que pertenece.

    ¿Cómo se hace?


    Firma


    • Editado LG DES lunes, 5 de noviembre de 2012 16:42
    lunes, 5 de noviembre de 2012 16:41

Respuestas

  • Al final he podido leer el fichero usando xml:

        Private Sub XML_CargarDT(NombreFicheroXML As String, TablaDestino As DataTable)
            Dim xmldoc As New XmlDocument
            xmldoc.Load(NombreFicheroXML)
            Call XML_CargarDT(xmldoc.DocumentElement, TablaDestino)
        End Sub
        Private Sub XML_CargarDT(ByRef NodeXml As XmlNode, ByVal dt As DataTable)
            If NodeXml.HasChildNodes() Then
                For Each xNode As XmlNode In NodeXml.ChildNodes
                    XML_CargarDT(xNode, dt)
                Next
            Else
                Dim dr As DataRow = dt.NewRow
                For Each oAttr As XmlAttribute In NodeXml.Attributes
                    dr.Item(oAttr.Name) = oAttr.Value
                Next
                dr.Item("XMLName") = NodeXml.Name
                dr.Item("XMLParent") = NodeXml.ParentNode.Name
                dt.Rows.Add(dr)
            End If
        End Sub

    La tabla destino tiene que tener los mismos campos/atributos que el XML, y 2 campos extras:

    XMLName para el codigo (que está en cada registro)

    XMLParent para la fecha (el elemento 'superior' de cada registro)


    Firma

    • Marcado como respuesta LG DES lunes, 12 de noviembre de 2012 9:08
    lunes, 12 de noviembre de 2012 9:07

Todas las respuestas

  •     Dim ds As New DataSet
        ds.ReadXml("c:\miFichero.xml")

    recuerda que el dataset contiene los datatables que sean necesarios al importar el xml.

    lunes, 5 de noviembre de 2012 16:46
  • De esta forma me crea un datatable por cada elemento (fecha/codigo), y yo los codigos los quiero con la fecha a la que pertenecen.

    • Editado LG DES lunes, 5 de noviembre de 2012 16:54
    lunes, 5 de noviembre de 2012 16:52
  • ¿Entonces lo que quieres es lo mostrado con este xml?:

    <?xml version="1.0" encoding="windows-1252"?>
    <info>
    <fecha20120101>
      <codigo>1</codigo>
      <prop1></prop1>
      <prop2></prop2>
      <prop3></prop3>
      <Nombre>Nombre1</Nombre>
    </fecha20120101>
    <fecha20120101>
      <codigo>1</codigo>
      <prop1>2</prop1>
      <prop2>1</prop2>
      <prop3>4</prop3>
      <Nombre>Nombre2</Nombre>
    </fecha20120101>
    <fecha20120101>
      <codigo>33</codigo>
      <prop1>2</prop1>
      <prop2>2</prop2>
      <prop3>5</prop3>
      <Nombre>Nombre33</Nombre>
    </fecha20120101>
    <fecha20120101>
      <codigo>4</codigo>
      <prop1>2</prop1>
      <prop2>1</prop2>
      <prop3>8</prop3>
      <Nombre>Nombre4</Nombre>
    </fecha20120101>
    <fecha20120101>
      <codigo>45</codigo>
      <prop1>2</prop1>
      <prop2>2</prop2>
      <prop3>3</prop3>
      <Nombre>Nombre45</Nombre>
    </fecha20120101>
    <fecha20120101>
      <codigo>99</codigo>
      <prop1>2</prop1>
      <prop2>1</prop2>
      <prop3>9</prop3>
      <Nombre>Nombre99</Nombre>
    </fecha20120101>
    <fecha20120101>
      <codigo>15</codigo>
      <prop1>2</prop1>
      <prop2>3</prop2>
      <prop3>5</prop3>
      <Nombre>Nombre15</Nombre>
    </fecha20120101>
    <fecha20120201>
      <codigo>250</codigo>
      <prop1>3</prop1>
      <prop2>1</prop2>
      <prop3>100</prop3>
      <Nombre>Nombre250</Nombre>
    </fecha20120201>
    <fecha20120301>
      <codigo>250</codigo>
      <prop1>3</prop1>
      <prop2>2</prop2>
      <prop3>100</prop3>
      <Nombre>Nombre250</Nombre>
    </fecha20120301>
    </info>

    ...con lo mostrado quiero decir al dataset obtenido con ReadXml

    lunes, 5 de noviembre de 2012 17:27
  • Casi!!!, quiero todos los registros en un unico datatable, con la fecha en cada registro.

    Con tu XML, me salen 3 datatables donde la fecha forma parte del nombre del datatable, y yo quiero 1 datatable con el campo fecha en todos los registros, pero claro, todo ello a partir del XML original.

    Gracias por la ayuda, a ver si se puede conseguir, gracias.


    Firma


    • Editado LG DES lunes, 5 de noviembre de 2012 17:42
    lunes, 5 de noviembre de 2012 17:41
  • Por explicarlo de una forma "sencilla", podemos ver una base de datos que contiene 2 tablas como la siguiente estructura xml:

    <basededatos>
      <tabla1>
        <registro1_t1>valor1</regristro1_t1>
        <registro2_t1>valor2</regristro2_t1>
        <registro3_t1>valor3</regristro3_t1>
      </tabla1>
      <tabla1>
        <registro1_t1>valor4</regristro1_t1>
        <registro2_t1>valor5</regristro2_t1>
        <registro3_t1>valor6</regristro3_t1>
      </tabla1>
      <tabla2>
        <registro1_t2>valor</regristro1_t2>
        <registro2_t2>valor</regristro2_t2>
        <registro3_t2>valor</regristro3_t2>
      </tabla2>
      <tabla2>
        <registro1_t2>valor4</regristro1_t2>
        <registro2_t2>valor5</regristro2_t2>
        <registro3_t2>valor6</regristro3_t2>
      </tabla2>
    </basededatos>

    pero tu quieres convertir los atributos de los elementos en valores, es decir, esto

    <elemento atributo1="12" atributo2="21">valor</elemento>

    en esto:

    <elemento>
      <atributo1>12</atributo1>
      <atributo2>21</atributo2>
      <valor>valor</valor>
    </elemento>

    Creo que vas a tener que hacerlo a mano, es decir, crear un datatable que se amolde a lo que quieres introducir, y leer el xml linea a linea para así agregar valor a valor a un datarow nuevo y agregarlo despues al datatable creado. (¡Creo!).

    Si nadie conoce alguna forma automatica, te puedo ayudar

    lunes, 5 de noviembre de 2012 17:59
  • Hombre, preferiria que fuera de forma automatica, pero si hay que programarlo, pues se programa. Te agradeceria tu ayuda para empezar a hacerlo.

    • Editado LG DES martes, 6 de noviembre de 2012 8:26
    martes, 6 de noviembre de 2012 8:25
  • Ahi va.

      Public Function obtenerDataTable(ByVal pathFichero As String) As DataTable
        obtenerDataTable = New DataTable("datos")
        obtenerDataTable.Columns.Add("fecha", System.Type.GetType("System.String"))
        obtenerDataTable.Columns.Add("codigo", System.Type.GetType("System.String"))
        obtenerDataTable.Columns.Add("prop1", System.Type.GetType("System.String"))
        obtenerDataTable.Columns.Add("prop2", System.Type.GetType("System.String"))
        obtenerDataTable.Columns.Add("prop3", System.Type.GetType("System.String"))
        obtenerDataTable.Columns.Add("nombre", System.Type.GetType("System.String"))
        Dim sr As New System.IO.StreamReader(pathFichero, System.Text.Encoding.GetEncoding("Windows-1252"))
        Dim linea As String
        Dim fecha, codigo, prop1, prop2, prop3, nombre As String
        Dim contenido As String()
        linea = sr.ReadLine
        Do
          linea = Trim(linea)
          If linea.StartsWith("<fecha") Then
            fecha = linea.Substring(6, 8)
          ElseIf linea.StartsWith("<codigo") Then
            contenido = linea.Split(TryCast(Nothing, Char()), StringSplitOptions.RemoveEmptyEntries)
            codigo = contenido(0).Replace("<codigo", "")
            prop1 = contenido(1).Replace("prop1=", "")
            prop1 = prop1.Trim(""""c)
            prop2 = contenido(2).Replace("prop2=", "")
            prop2 = prop2.Trim(""""c)
            prop3 = contenido(3).Replace("prop3=", "")
            prop3 = prop3.Trim(""""c)
            nombre = contenido(4).Replace("Nombre=", "")
            nombre = nombre.Trim(""""c)
            Dim fila As DataRow = obtenerDataTable.NewRow
            fila("fecha") = fecha
            fila("codigo") = codigo
            fila("prop1") = prop1
            fila("prop2") = prop2
            fila("prop3") = prop3
            fila("nombre") = nombre
            obtenerDataTable.Rows.Add(fila)
          End If
          linea = sr.ReadLine
        Loop Until linea Is Nothing
        sr.Close()
        sr.Dispose()
        sr = Nothing
      End Function


    martes, 6 de noviembre de 2012 18:19
  • Gracias por el codigo, pero estoy viendo que al final estas procesando el xml como un fichero de texto 'normal' (linea a linea).

    Entiendo que al ser un xml debería poder leerlo directamente, no procesar linea a linea, así que pregunto (también a todo el grupo):

    ¿ Considerais este xml bien formado?

    <?xml version="1.0" encoding="windows-1252"?>
    <info>
    <fecha20120101>
      <codigo2  prop1="2" prop2="1" prop3="4" 	Nombre="Nombre2" />
      <codigo33 prop1="2" prop2="2" prop3="5" 	Nombre="Nombre33" />
      <codigo45 prop1="2" prop2="2" prop3="3" 	Nombre="Nombre45" />
    </fecha20120101>
    <fecha20120201>
      <codigo250 prop1="3" prop2="1" prop3="100" 	Nombre="Nombre250" />
      <codigo33 prop1="2" prop2="2" prop3="45" 	Nombre="Nombre33" />
    </fecha20120201>
    <fecha20120301>
      <codigo45 prop1="2" prop2="12" prop3="3" 	Nombre="Nombre45" />
      <codigo250 prop1="3" prop2="2" prop3="100" 	Nombre="Nombre250" />
    </fecha20120301>
    </info>

    La información que contiene son registros con clave primaria Codigo<n>, con varias propiedades/campos que cambian en determinadas fechas.

    Espero vuestros comentarios, gracias


    Firma

    miércoles, 7 de noviembre de 2012 11:01
  • Al final he podido leer el fichero usando xml:

        Private Sub XML_CargarDT(NombreFicheroXML As String, TablaDestino As DataTable)
            Dim xmldoc As New XmlDocument
            xmldoc.Load(NombreFicheroXML)
            Call XML_CargarDT(xmldoc.DocumentElement, TablaDestino)
        End Sub
        Private Sub XML_CargarDT(ByRef NodeXml As XmlNode, ByVal dt As DataTable)
            If NodeXml.HasChildNodes() Then
                For Each xNode As XmlNode In NodeXml.ChildNodes
                    XML_CargarDT(xNode, dt)
                Next
            Else
                Dim dr As DataRow = dt.NewRow
                For Each oAttr As XmlAttribute In NodeXml.Attributes
                    dr.Item(oAttr.Name) = oAttr.Value
                Next
                dr.Item("XMLName") = NodeXml.Name
                dr.Item("XMLParent") = NodeXml.ParentNode.Name
                dt.Rows.Add(dr)
            End If
        End Sub

    La tabla destino tiene que tener los mismos campos/atributos que el XML, y 2 campos extras:

    XMLName para el codigo (que está en cada registro)

    XMLParent para la fecha (el elemento 'superior' de cada registro)


    Firma

    • Marcado como respuesta LG DES lunes, 12 de noviembre de 2012 9:08
    lunes, 12 de noviembre de 2012 9:07