2010-01-27 4 views
1

J'ai un XmlWriter comme suitIndentation en XML créé par programme en C#

XmlWriterSettings settings = new XmlWriterSettings(); 
settings.Indent = true; 
settings.NewLineHandling = NewLineHandling.Entitize; 
using (XmlWriter currentWriter = XmlWriter.Create(filePath, settings)) 
{ 
    workingXmlDocument.WriteTo(currentWriter); 
    currentWriter.Flush(); 
} // using (XmlWriter xw = XmlWriter.Create(FilePath)) 

Je créé par programme un document XML que je suis en train d'écrire avec cela, et il est ÉCRITURE très bien, sauf que j'ai un bloc d'éléments qui sont créés dans une boucle et il met tous ces éléments sur une ligne. Si vous avez besoin de voir un autre code du programme, faites le moi savoir et je peux le mettre ici. J'accueille toutes les idées même si elles ne sont pas des solutions complètes.

Mise à jour - la méthode complète où le problème se passe

private void XMLReaderUtil(string filePath) 
    { 
     XDocument workingXmlDocument; 

     using (XmlReader currentReader = XmlReader.Create(filePath)) 
     { 

      workingXmlDocument = XDocument.Load(currentReader); 

      foreach (KeyValuePair<string, string> currentIteration in logDataRaw) 
      { 
       FileInfo currentEntry = new FileInfo(currentIteration.Value); 

       string testString = currentEntry.Directory.Name; 

       if (testString.Contains(" ")) { testString = testString.Replace(" ", "_"); } 

       IEnumerable<XElement> list = from XElement e in workingXmlDocument.Descendants(wixNS + testString) 
              select e; 

       DirectoryInfo temp = currentEntry.Directory; 

       while (list.Count() == 0 && !temp.Name.Contains(":")) 
       { 
        testString = temp.Name; 

        if (testString.Contains(" ")) { testString = testString.Replace(" ", "_"); } 

        list = from XElement e in workingXmlDocument.Descendants(wixNS + testString) 
          select e; 
        temp = temp.Parent; 
       } // while (list.Count() == 0 && !temp.Name.Contains(":")) 

       if (list.Count() == 0) 
       { 
        IEnumerable<XElement> targetDirectory = 
         from XElement e in workingXmlDocument.Descendants(wixNS + "Directory") 
         where e.Attribute("Id").Value == "TARGETDIR" 
         select e; 

        var outXml = new XElement("root"); 
        foreach (var item in targetDirectory) 
        { 
         item.Add(new XElement(
          "Directory", 
          new XAttribute("new", 1))); 

         outXml.Add(item); 
        } 

        outXml.Save(@"c:\users\adkins\desktop\temp.wxs", SaveOptions.None); 

       } 
      } // foreach (KeyValuePair<string, string> kvp in xmlDataChanged) 
      // return workingXmlDocument; 
     } // using (XmlReader sr = XmlReader.Create(FilePath)) 

     IEnumerable<XElement> cleanup = 
      from XElement e in workingXmlDocument.Descendants(wixNS + "Directory") 
      select e; 
     Collection<string> keep = new Collection<string>(); 
     XElement[] blah; 
     blah = cleanup.ToArray(); 

     for (int i = 0; i < blah.Length; i++) 
     { 
      if (!keep.Contains(blah[i].Attribute("Id").Value)) 
      { 
       keep.Add(blah[i].Attribute("Id").Value); 
      } 
      else 
      { 
       blah[i].Remove(); 
      } 
     } 

     workingXmlDocument.Save(filePath, SaveOptions.None); 

     // XMLWriter attempt 
     //XmlWriterSettings settings = new XmlWriterSettings(); 
     //settings.Indent = true; 
     //settings.IndentChars = "\t"; 
     //settings.NewLineHandling = NewLineHandling.Entitize; 
     //settings.NewLineChars = "\n"; 
     //settings.CloseOutput = true; 
     //settings.Encoding = System.Text.Encoding.UTF8; 
     //using (XmlWriter currentWriter = XmlWriter.Create(filePath, settings)) 
     //{ 
     // workingXmlDocument.WriteTo(currentWriter); 
     // currentWriter.Flush(); 
     //} // using (XmlWriter xw = XmlWriter.Create(FilePath)) 

     //TextWriter test run - nothing changed 
     //XmlTextWriter writer = new XmlTextWriter(filePath, System.Text.Encoding.UTF8); 
     //writer.Formatting = Formatting.Indented; 
     //writer.IndentChar = '\t'; 
     //writer.Indentation = 1; 

     //workingXmlDocument.WriteTo(writer); 
     //writer.Flush(); 
     //writer.Close(); 

    } 

Voici la méthode de problème complet. Il comprend mes tentatives de diverses formes de sauvegarde du fichier. C'est un désordre complet dû à mes efforts pour résoudre ce problème et les problèmes que j'ai rencontrés avant d'arriver à celui-ci. Toute aide serait grandement appréciée!

La variable "logDataRaw" est un dictionnaire contenant le nom d'un fichier et le chemin vers lequel il est stocké. Si vous avez besoin d'autres précisions s'il vous plaît faites le moi savoir. Pourquoi ne pas simplement utiliser XElement.Save() au lieu de XmlWriter?

+0

Oui, merci de poster un code qui fait ceci: "J'ai un bloc d'éléments qui sont créés en boucle et qui met tous ces éléments sur une seule ligne" – Restuta

+0

Donc une partie est affichée correctement et une partie en est ne pas? Normalement, pour corriger mes indentions XML, je le charge honnêtement en VS et je clique sur le bouton "Tout formater".Cela étant dit, si le XML doit être lu par un ordinateur, vous économisez des octets en supprimant les espaces. –

+1

À côté: Vous devez vous assurer que vous avez défini 'XmlWriterSettings.CloseOutput' sur' true' de sorte que lorsque l'éditeur est supprimé, il ferme le fichier. –

Répondre

2

Le problème était que je charge le fichier XML à travers un XMLReader. Une fois que j'ai enlevé cela et juste chargé directement dans mon XDocument que tout a bien fonctionné.

+0

Comme c'est étrange! J'ai le même problème et tu as raison ... Je ne peux pas croire que XmlReader affecte XmlWriter ... – Ricky

1

http://msdn.microsoft.com/en-us/library/bb538458.aspx

EDIT:

Je viens de rencontrer le bit de code suivant

 var xml = new XElement("root", 
           new XElement("node", 
              new XAttribute("index", 1) 
           ), 
           new XElement("node", 
              new XAttribute("index", 2) 
           ), 
           new XElement("node", 
              new XAttribute("index", 3) 
           ), 
           new XElement("node", 
              new XAttribute("index", 4) 
           ) 
      ); 

     IEnumerable<XElement> ieXml = 
      from XElement e in xml.Elements() 
      select e; 

     var outXml = new XElement("root"); 
     foreach (var item in ieXml) 
     { 
      item.Add(new XElement(
       "Directory", 
       new XAttribute("new", 1))); 

      outXml.Add(item); 
     } 


     outXml.Save(@"d:\foo.xml", SaveOptions.None); 

et le résultat est mis en forme

<?xml version="1.0" encoding="utf-8"?> 
<root> 
    <node index="1"> 
    <Directory new="1" /> 
    </node> 
    <node index="2"> 
    <Directory new="1" /> 
    </node> 
    <node index="3"> 
    <Directory new="1" /> 
    </node> 
    <node index="4"> 
    <Directory new="1" /> 
    </node> 
</root> 

Je ne sais pas ce que vous » re faire différemment, mais cela fonctionne.

+0

@Chad: Je crois que le PO veut sérialiser le document entier, pas seulement un élément. Donc, pourrais-je vous suggérer de recommander XDocument.Save() 'à la place. Bien que je suspecte que juste utilise 'XmlWriter' sous le capot. –

+0

@Chad: J'ai essayé cela avec XDocument au lieu de XElement, mais j'ai obtenu la même sortie. – Adkins

+1

@Jeff, quelles sont les options de sauvegarde que vous utilisez? http://msdn.microsoft.com/en-us/library/system.xml.linq.saveoptions.aspx Comme il devrait le garder – CaffGeek

0

Vous pourriez avoir besoin d'utiliser un XmlTextWriter avec encodage par défaut au lieu de XmlWriter et définir la propriété mise en forme de l'objet Writer pour Formatting.Indented

+0

J'ai essayé ça. J'ai mis à jour mon code pour montrer ce que j'ai essayé d'économiser. – Adkins

0

Si quelqu'un utilise XDocument et a encore des problèmes avec l'enregistrement XML en fichier avec tiret correct cela peut vous aider, il a fait pour moi:

  1. En plus de la réponse du Tchad je devais utiliser XName.Get (...) lorsque vous spécifiez le nom XElement:

    var xdoc = new XDocument(
          new XDeclaration("1.0", "utf-8", "yes"), 
          new XElement(XName.Get("TranslationContainer"), 
             new XElement(XName.Get("Translations")))); 
    
  2. Vérifiez que vous disposez d'un xml bien formaté (ne pas le texte en dehors des balises xml)

Bonne chance.