2009-05-21 16 views
5

Sto cercando di ottenere un file XML in un insieme di dati e sto usando il seguente codice:Importa XML in Dataset C#

DataSet ds = new DataSet("TestDataSet"); 
ds.ReadXml(FileName); 

e questo file xml:

<Catalog> 
<Rec> 
    <ITEM dt:dt="string"/> 
    <QTY dt:dt="string">1</QTY> 
    <SUB dt:dt="string">1</SUB> 
    <CATALOG dt:dt="string">ABC123</CATALOG> 
    </Rec> 
    <Rec> 
    <ITEM dt:dt="string"/> 
    <QTY dt:dt="string">1</QTY> 
    <SUB dt:dt="string">1</SUB> 
    <CATALOG dt:dt="string">ABC124</CATALOG> 
    </Rec> 
    <Rec> 
    <ITEM dt:dt="string"/> 
    <QTY dt:dt="string">1</QTY> 
    <SUB dt:dt="string">1</SUB> 
    <CATALOG dt:dt="string">ABC125</CATALOG> 
    </Rec> 
</Catalog> 

Il guaio è che il dopo aver impostato un orologio su ds, sembra che contenga solo una tabella chiamata Rec e una colonna chiamata Rec_Id. Se rimuovo il tipo di dati "dt: dt =" String "", tutto funziona correttamente.

Sto usando C# .NET 2008 ...

Può qualcuno si prega di avvisare il modo corretto per importare questi dati senza dover modificare il file XML?

Grazie

+0

come viene definito lo spazio dei nomi dt? – Baget

+0

Ho fatto una domanda simile e ho ricevuto una bella risposta che mi ha aiutato. Puoi dare un'occhiata al mio [SO] (http://stackoverflow.com/questions/772946/import-xml-to-sql-using-c) – adopilot

risposta

1

Affinché il ReadXml di funzionare correttamente in questo caso, penso che è necessario specificare uno schema nel file XML. Altrimenti, il lettore non saprà cosa fare con i tipi di dati.

+0

Bingo. Per riferimento, prova a fare un WriteXML su un DataSet conosciuto e guarda cosa produce. Noterai nel nodo radice per il nome della classe che aggiunge gli attributi dello spazio dei nomi che Jon ha menzionato. –

5

Non appena si definisce lo spazio dei nomi XML utilizzato negli elementi XML, è possibile importarlo facilmente, nessun problema.

È necessario avere il vostro XML simile a questa:

<Catalog xmlns:dt="some-xml-namespace-here"> 
<Rec> 
    <ITEM dt:dt="string"/> 
    <QTY dt:dt="string">1</QTY> 
    <SUB dt:dt="string">1</SUB> 
    <CATALOG dt:dt="string">ABC123</CATALOG> 
    </Rec> 
    ..... 
</Catalog> 

Dopo faccio questo, i tuoi due linee di lavoro di codice come un fascino ed i dati vengono importati, non è un problema (in 5 tavoli all'interno del DataSet).

Marc

+0

Questo non può essere convalidato rispetto a qualsiasi schema, ma se si aggiunge xmlns = "dt", è possibile creare uno schema che convalidi l'xml. –

+0

Vero - ma il poster originale non ha richiesto la convalida: vuole solo importare il file in un set di dati. Questo può essere realizzato come ho mostrato. –

0

In questo modo sarà parseable. Lo spazio dei nomi dt di solito si riferisce a xmlns: dt = "urn: schemas-microsoft-com: datatypes". Qualcosa o qualcuno incasinato il tuo XML, ma se si deve essere in grado di importare, è possibile solo modificare i xmlns attributi sull'elemento catalogo come mostrato:

  string xml = @"<Catalog xmlns=""dt"" xmlns:dt=""dt""> 
         <Rec> 
         <ITEM dt:dt=""string""/> 
         <QTY dt:dt=""string"">1</QTY> 
         <SUB dt:dt=""string"">1</SUB> 
         <CATALOG dt:dt=""string"">ABC123</CATALOG> 
         </Rec> 
         <Rec> 
         <ITEM dt:dt=""string""/> 
         <QTY dt:dt=""string"">1</QTY> 
         <SUB dt:dt=""string"">1</SUB> 
         <CATALOG dt:dt=""string"">ABC124</CATALOG> 
         </Rec> 
         <Rec> 
         <ITEM dt:dt=""string""/> 
         <QTY dt:dt=""string"">1</QTY> 
         <SUB dt:dt=""string"">1</SUB> 
         <CATALOG dt:dt=""string"">ABC125</CATALOG> 
         </Rec> 
         </Catalog>"; 

     DataSet ds = new DataSet("Whatev"); 

     TextReader txtReader = new StringReader(xml); 
     XmlReader reader = new XmlTextReader(txtReader); 
     ds.ReadXml(reader); 
     Debug.Assert(ds.Tables.Count ==5); 
     Debug.Assert((string)ds.Tables[2].Rows[0][0] == "string"); 
     Debug.Assert((string)ds.Tables[3].Rows[0][1] == "1"); 

anche Marc è corretto, ma con la definizione di cui sopra si può generare uno schema corrispondente:

<xs:schema xmlns:dt="dt" attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="dt" xmlns:xs="http://www.w3.org/2001/XMLSchema"><xs:element name="Catalog"><xs:complexType> <xs:sequence><xs:element maxOccurs="unbounded" name="Rec"><xs:complexType><xs:sequence><xs:element name="ITEM"><xs:complexType><xs:attribute ref="dt:dt" use="required" /></xs:complexType></xs:element><xs:element name="QTY"><xs:complexType> 
       <xs:simpleContent><xs:extension base="xs:unsignedByte"><xs:attribute ref="dt:dt" use="required" /></xs:extension></xs:simpleContent></xs:complexType> 
      </xs:element><xs:element name="SUB"><xs:complexType><xs:simpleContent><xs:extension base="xs:unsignedByte"><xs:attribute ref="dt:dt" use="required" /></xs:extension></xs:simpleContent></xs:complexType></xs:element><xs:element name="CATALOG"><xs:complexType><xs:simpleContent><xs:extension base="xs:string"><xs:attribute ref="dt:dt" use="required" /></xs:extension></xs:simpleContent></xs:complexType></xs:element></xs:sequence></xs:complexType></xs:element></xs:sequence></xs:complexType></xs:element><xs:attribute name="dt" type="xs:string" /></xs:schema> 

L'attributo "dt" è un attributo di riferimento. Quindi l'xml non può essere valido contro qualsiasi schema senza la dichiarazione xmlns = "ds".

+0

Non mi permette di incollare l'intero schema in ... –

+0

Dovevo rimuovere tutti gli spazi bianchi dallo schema per poterlo mostrare tutto. –

+0

Come il file viene generato automaticamente da un altro programma, esiste un modo per specificare uno schema tramite il programma C# prima di leggere il file nel set di dati? La ragione per cui chiedo è che non voglio dover (a meno che non sia facile farlo) modificare il file xml per aggiungere uno schema in modo che il mio software possa leggerlo; Sto cercando di automatizzare questo senza l'intervento umano !! :) Inoltre, qual è il modo più semplice per creare uno schema? Esistono procedure guidate o software che possono aiutare in questo? Grazie per il vostro aiuto ragazzi :) –

1
DataSet ds = new DataSet("Whatev"); 
DataTable catalog = ds.Tables.Add("Catalog"); 
DataColumn recCol = catalog.Columns.Add("Rec"); 
DataTable rec = ds.Tables.Add("Rec"); 

rec.Columns.AddRange(new DataColumn[] { 
    new DataColumn("ITEM", typeof(string)), 
    new DataColumn("QTY", typeof(string)), 
    new DataColumn("SUB", typeof(string)), 
    new DataColumn("CATALOG", typeof(string)) 
});    

XmlDocument doc = new XmlDocument(); 
doc.LoadXml(xml); 
foreach (XmlNode recNode in doc.GetElementsByTagName("Rec")) 
{ 
    DataRow row = rec.Rows.Add(
     recNode["ITEM"].InnerText, 
     recNode["QTY"].InnerText, 
     recNode["SUB"].InnerText, 
     recNode["CATALOG"].InnerText); 
} 

Ci ya go. Ora ci saranno due tabelle, Catalog e Rec. Sospetto che tu voglia solo Rec, perché il catalogo è inutile. Quindi, è sufficiente rimuovere il codice datatable catalogo, se questo è il caso, o aggiungere attributo un id ogni riga catalogo e collegarlo al rec:

DataSet ds = new DataSet("Whatev"); 
DataTable catalog = ds.Tables.Add("Catalog"); 
DataColumn idCol = catalog.Columns.Add("Id"); 
DataTable rec = ds.Tables.Add("Rec"); 

rec.Columns.AddRange(new DataColumn[] { 
    new DataColumn("ITEM", typeof(string)), 
    new DataColumn("QTY", typeof(string)), 
    new DataColumn("SUB", typeof(string)), 
    new DataColumn("CATALOG", typeof(string)) 
}); 

catalog.ChildRelations.Add("catToRecRelation", idCol, rec.Columns["CATALOG"]); 

XmlDocument doc = new XmlDocument(); 
doc.LoadXml(xml); 
foreach (XmlNode recNode in doc.GetElementsByTagName("Rec")) 
{ 
    // Create id in parent Catalog node, based on CATALOG value 
    catalog.Rows.Add(recNode["CATALOG"].InnerText); 

    DataRow row = rec.Rows.Add(
    recNode["ITEM"].InnerText, 
    recNode["QTY"].InnerText, 
    recNode["SUB"].InnerText, 
    recNode["CATALOG"].InnerText); 
} 

var childRows = catalog.Rows[0].GetChildRows("catToRecRelation"); 
0

io uso questo codice ...

Per generare il codice XML:

// you need to create a datatable, from a sql query, linq, your choice... 
DataTable _dt = new DataTable(); 
// write the datatable with schema 
dt.WriteXml("datatable.xml", XmlWriteMode.WriteSchema); 

Per leggere il codice XML:

DataTable dt = new DataTable(); 
dt.Clear(); 
dt.ReadXml("datatable.xml", XmlReadMode.ReadSchema); 

Il risultato DataTable possono essere integrate con queste funzioni, in questo modo è possibile convertirlo in IList, è necessario creare un oggetto con lo stesso modello di colonne, è molto più pratico in questo modo:

public IList<T> toList<T>(DataTable table) 
{ 
    List<T> list = new List<T>(); 
    T item; 
    Type listItemType = typeof(T); 

    for (int i = 0; i < table.Rows.Count; i++) 
    { 
     item = (T)Activator.CreateInstance(listItemType); 
     mapRow(item, table.Rows[i], listItemType); 
     list.Add(item); 
    } 
    return list; 
} 
private void mapRow(object vOb, System.Data.DataRow dr, Type type) 
{ 
    try 
    { 
     for (int col = 0; col < dr.Table.Columns.Count; col++) 
     { 
      var columnName = dr.Table.Columns[col].ColumnName; 
      var prop = type.GetProperty(columnName.ToUpper()); 
      object data = dr[col]; 
      prop.SetValue(vOb, data, null); 
     } 
    } 
    catch (Exception ex) 
    { 
     throw ex; 
    } 
} 

In realtà, sto lavorando a un'app che utilizza l'XML generato dalle tabelle SQL. Fondamentalmente, utilizzare le funzioni di cui sopra, creo un'altra piccola app (per supportare il primo) che esegue la scansione del pacchetto di XML (XML per tabella) e creare i livelli business, accesso, oggetto e un controllo di flusso per la scrittura corretta & lettura del XML.

1

no se mucho ingles así que escribiré en español. Yo tenia el mismo problema e después de una continua búsqueda ademas de probar muchas veces, encontré la solución en las siguientes lineas.

DataSet dataSet = new DataSet(); 
DataTable dataTable = new DataTable("table1"); 
dataTable.Columns.Add("col1", typeof(string)); 
dataSet.Tables.Add(dataTable); 

string xmlData = "<XmlDS><table1><col1>Value1</col1></table1><table1><col1>Value2</col1></table1></XmlDS>"; 

System.IO.StringReader xmlSR = new System.IO.StringReader(xmlData); 
dataSet.ReadXml(xmlSR, XmlReadMode.IgnoreSchema); 

Para información mas News dettagli pueden ver esta página http://msdn.microsoft.com/es-es/library/fx29c3yd(v=vs.110).aspx

Espero les ayude como ami.

Saludos