2011-08-03 2 views
8

J'ai un problème lorsque j'écris un DataSet en XML qui a une colonne de type DateTime et que je veux contrôler le format de sortie.Formats DateTime personnalisés lors de l'utilisation de DataSet.WriteXml dans .NET

DataSet data = LoadDataSet(); 
data.Tables[0].Rows[0]["MyDate"] = DateTime.Now; 
data.WriteXml(myFile); 

Par défaut, le format du DateTime dans le fichier XML semble être comme suit:

2011-08-02T17:39:00-07:00 

Je voudrais utiliser un format de date personnalisé ou à la bande moins l'info fuseau horaire.

Existe-t-il un moyen de contrôler le format des colonnes DateTime dans mon jeu de données XML? Mon instinct dit non car je suppose que cela est fait de cette façon pour faciliter la conversion des données à travers les fuseaux horaires, mais j'ai remarqué que je peux lire avec succès XML DataSet même si les balises de colonne DateTime omettent les données de fuseau horaire alors j'espérais Je peux faire quelque chose d'analogue en écrivant en XML.

+1

j'ai vu certains développeurs utilisent des astuces comme l'ajout d'une autre colonne appelée ["MyDateString"] où ils utilisent DateTime.Now.ToShortDateString(), ne dit pas que c'est idéal, mais je l'ai vu de première main dans les classes de sérialisation pour certains messages que nous échangeons avec d'autres partenaires :) – kd7

+0

Ouais, je viens de mentionner ça à un collègue. Ce sera probablement notre plan de repli. –

+0

Pouvez-vous définir un schéma XSLT et l'appliquer à XML, ou est-ce que ce serait une surcharge dans votre cas? – sll

Répondre

-1

Il y a un format standard pour DateTime en XML. C'est le format que WriteXml utilisera. Si vous avez besoin d'un format différent, vous n'avez pas besoin d'utiliser DateTime. Comme d'autres l'ont dit, utilisez String à la place.

+0

Il s'agit d'une zone grise, il n'y a pas de référence de schéma dans les fichiers générés, donc rien ne force explicitement les balises DateTime de WriteXml à être de type xsd: date. Je suis d'accord que xsd: date a un format strict, mais je ne suis pas sûr que cela soit nécessairement utilisé ici. –

+0

Votre idée nécessiterait que 'WriteXml' génère des données dans un format que le schéma de' WriteXmlSchema' ne validerait pas. Cela semble improbable. –

1

Appliquer transformation XSLT DataSet: (à partir MSDN) (je crois que vous trouverez par exemple XSLT pour convertir le format DateTime, ou voir post on SO regarding XSLT and DateTIme formats)

DataSet custDS = new DataSet("CustomerDataSet"); 
XmlDataDocument xmlDoc = new XmlDataDocument(custDS); 

XslTransform xslTran = new XslTransform(); 
xslTran.Load("transform.xsl"); 

XmlTextWriter writer = new XmlTextWriter("xslt_output.html", 
    System.Text.Encoding.UTF8); 

xslTran.Transform(xmlDoc, null, writer); 
writer.Close(); 
+0

nous sommes en train de le transformer via XSLT après le fait déjà (pour l'intégration avec un système tiers), mais le format de sortie se soucie de AM/PM alors pour l'instant nous écrivons juste la logique XSLT conditionnelle pour analyser la date de 24 heures format et le transformer en un format AM/PM de 12 heures. Un peu désordonné mais ça va faire l'affaire. –

11

Cette solution de contournement peut convenir si vous pouvez vivre avec uniquement les informations de fuseau horaire qui sont supprimées. La valeur par défaut pour la propriété DateTimeMode des colonnes DateTime dans DataSets est UnspecifiedLocal. Vous pouvez définir explicitement le DateTimeMode sur Unspecified, ce qui signifie que la partie timezone n'est pas sérialisée.

par exemple.

Vous pouvez utiliser une fonction comme ceci:

public static void RemoveTimezoneForDataSet(DataSet ds) 
    { 
     foreach (DataTable dt in ds.Tables) 
     { 
      foreach (DataColumn dc in dt.Columns) 
      { 

       if (dc.DataType == typeof(DateTime)) 
       { 
        dc.DateTimeMode = DataSetDateTime.Unspecified; 
       } 
      } 
     } 
    } 

Exemple d'utilisation:

DataSet ds = new DataSet(); 
    DataTable dt = new DataTable("t1"); 
    dt.Columns.Add("ID", typeof(int)); 
    dt.Columns.Add("DT", typeof(DateTime)); 
    dt.Rows.Add(new object[] { 1, new DateTime(2009, 1, 1) }); 
    dt.Rows.Add(new object[] { 2, new DateTime(2010, 12, 23) }); 

    ds.Tables.Add(dt); 

    ds.WriteXml("c:\\Standard.xml"); 

    RemoveTimezoneForDataSet(ds); 

    ds.WriteXml("c:\\WithoutTimezone.xml"); 

Sortie:

Standard.xml:

<?xml version="1.0" standalone="yes"?> 
<NewDataSet> 
    <t1> 
    <ID>1</ID> 
    <DT>2009-01-01T00:00:00+11:00</DT> 
    </t1> 
    <t1> 
    <ID>2</ID> 
    <DT>2010-12-23T00:00:00+11:00</DT> 
    </t1> 
</NewDataSet> 

WithoutTimezone.xml :

<?xml version="1.0" standalone="yes"?> 
<NewDataSet> 
    <t1> 
    <ID>1</ID> 
    <DT>2009-01-01T00:00:00</DT> 
    </t1> 
    <t1> 
    <ID>2</ID> 
    <DT>2010-12-23T00:00:00</DT> 
    </t1> 
</NewDataSet> 

Si vous ne voulez pas l'idée de modifier les DataColumns de votre DataSet d'origine, vous pouvez faire une copie, puis appelez la fonction sur la copie.

+0

Excellent. Merci. Il semblerait que seul DataSetDateTime.Unspecified fonctionnera parce que j'obtiens un message d'erreur essayant d'utiliser LocalTime - le mode ne peut pas être changé si la table a déjà des données. –

-1

Si le fichier est régulier et que le fichier XML exporté vous semble correct, vous pouvez simplement le réécrire en utilisant une simple boucle. Solution facile et rapide.Utilisez une partie de mon code si vous voulez:

private void rewriteXML(string oldFile, string newFile, int startPos, int strLength) 
     { 
      try 
      { 
       File.Delete(newFile); 
      } 
      catch { Console.WriteLine("File didn't existed."); } 
      StreamReader SR = new StreamReader(oldFile); 
      string data; 
      StreamWriter SW = new StreamWriter(newFile); 
      while ((data = SR.ReadLine()) != null) 
      { 
       if (data.Contains("<start>")) 
       { 
        string ln_tmp = data.Replace(" ", ""); 
        string newline = " <start>" + ln_tmp.Substring(startPos, strLength) + "</start>"; 
        SW.WriteLine(newline); 
       } 
       else 
        SW.WriteLine(data); 
      } 
      SR.Close(); 
      SW.Close(); 
     } 

La sortie est comme:

<start>19:34</start> 

Au lieu de:

<start>2013-03-17T19:34:00+01:00</start> 
+0

Le code n'implémente pas les blocs 'using', et ce bloc try/catch cachera les exceptions autres que le fichier non trouvé. –

Questions connexes