2009-05-21 7 views
5

Je suis en train d'obtenir un fichier XML dans un ensemble de données et je suis en utilisant le code suivant:XML d'importation dans Dataset C#

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

et ce fichier 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> 

Le problème est que le après avoir placé une surveillance sur ds, il semble seulement contenir une table appelée Rec et une colonne appelée Rec_Id. Si je supprime le type de données "dt: dt =" String "", tout fonctionne correctement.

J'utilise C# .net 2008 ...

Quelqu'un peut-il s'il vous plaît informer de la bonne manière d'importer ces données sans avoir à modifier le fichier xml?

Merci

+0

Comment l'espace de noms dt est-il défini? – Baget

+0

J'ai posé une question similaire et obtenir une bonne réponse qui m'a aidé. Vous pouvez jeter un oeil mon [SO] (http://stackoverflow.com/questions/772946/import-xml-to-sql-using-c) – adopilot

Répondre

1

Pour que le ReadXml fonctionne correctement dans ce cas, je pense que vous devez spécifier un schéma dans votre fichier XML. Sinon, le lecteur ne saura pas quoi faire avec les types de données.

+0

Bingo. Pour référence, essayez de faire un WriteXML sur un DataSet connu et voir ce qu'il produit. Vous remarquerez dans le nœud racine pour le nom de la classe, il ajoute les attributs d'espace de noms Jon mentionné. –

5

Dès que vous définissez votre espace de noms XML utilisé dans les éléments XML, vous pouvez facilement l'importer - pas de problème.

Vous devez avoir votre look XML quelque chose comme ceci:

<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> 

Après je fais cela, vos deux lignes de travail de code comme un charme et les données sont importées, pas de problème (en 5 tables à l'intérieur du DataSet).

Marc

+0

Cela ne peut être validé par aucun schéma, mais si vous ajoutez également xmlns = "dt", vous pouvez créer un schéma qui validera le fichier XML. –

+0

Vrai - mais l'affiche originale n'a pas demandé de validation - il veut seulement importer le fichier dans un ensemble de données. Cela peut être accompli comme je l'ai montré. –

0

Ceci le rendra analysable. L'espace de noms dt fait généralement référence à xmlns: dt = "urn: schemas-microsoft-com: datatypes". Quelque chose ou quelqu'un foiré votre XML, mais si vous devez pouvoir importer, vous pouvez simplement modifier les xmlns attributs sur l'élément de catalogue comme indiqué:

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

Aussi Marc est correct, mais avec la définition ci-dessus vous peut générer un schéma d'adaptation:

<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'attribut « dt » est un attribut de référence. Donc, le xml ne peut pas non plus être valide avec n'importe quel schéma sans la déclaration xmlns = "ds".

+0

Il ne me laissera pas coller le schéma entier dans ... –

+0

A dû enlever tous les espaces du schéma pour pouvoir l'avoir montrer tout. –

+0

Comme le fichier est automatiquement généré par un autre programme, est-il possible de spécifier un schéma via le programme C# avant de lire le fichier dans l'ensemble de données? La raison pour laquelle je demande est que je ne veux pas avoir (à moins que ce soit facile de le faire) avoir à modifier le fichier xml pour ajouter un schéma afin que mon logiciel puisse le lire; J'essaye d'automatiser ceci sans intervention humaine !! :) En outre, quelle est la manière la plus simple de créer un schéma? Y a-t-il des assistants ou des logiciels qui peuvent vous aider? Merci pour votre aide les gars :) –

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

Il y a go. Maintenant, il y aura deux tables, Catalogue et Rec. Je suppose que vous ne voulez que Rec, car Catalog est inutile. Donc, il suffit de retirer le catalogue du code datatable si tel est le cas, ou ajouter un attribut id chaque ligne de catalogue et de le relier à la recommandation:

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

J'utilise ce code ...

Pour générer le 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); 

Pour lire le XML:

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

Le résultat datatable peut être complétée par ces fonctions, de cette façon vous pouvez le convertir en IList, vous devez créer un objet avec le même modèle de colonnes, c'est vraiment plus pratique de cette façon:

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

En fait, je travaille sur une application qui utilise XML généré à partir de tables SQL. Fondamentalement, utiliser les fonctions ci-dessus, je crée d'autres petites applications (pour soutenir le premier) qui analysent le paquet de XML (XML par table) et créer les couches métier, accès, objet et un contrôle de flux pour l'écriture correcte de la XML.

1

aucun commentaire n'est demandé dans cet établissement. Yo tenia el mismo problema y 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 mas información detallada pueden ver esta pagina http://msdn.microsoft.com/es-es/library/fx29c3yd(v=vs.110).aspx

Espero les Fernando Ayude COME ami.

Saludos