Avatar billede globen Nybegynder
25. februar 2010 - 14:27 Der er 8 kommentarer og
1 løsning

XmlDocument.Save(string path)

Hej eksperter!

Betragt flg. kode:

System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
doc.LoadXml("<TestDoc><TestElement></TestElement></TestDoc>");
doc.Save("save.xml");
System.IO.File.WriteAllText("textfile.xml", doc.OuterXml);

Jeg udskriver xml'en på to måder, og de to måder har nogle betydelige forskelle:

save.xml
--------------------------------------------------
<TestDoc>
  <TestElement>
  </TestElement>
</TestDoc>
--------------------------------------------------

textfile.xml
--------------------------------------------------
<TestDoc><TestElement></TestElement></TestDoc>
--------------------------------------------------

Jeg oplevede dette som et problem i et scenarie hvor jeg i en xml schema validering tjekker på om nogle elementer er tomme. Hvilket ovenstående element 'TestElement' ikker er efter persistering med Save metoden. Save manipulerer med andre ord indholdet af xml elementerne, da den blandt andet indsætter linieskift inden i TestElelement. I mit hoved er dette en bug!

200 points til hvem end der kan argumentere imod!
Avatar billede mbulow Nybegynder
25. februar 2010 - 16:50 #1
Vi er helt enige i at der er meget stor forskel på de to output. Som du selv skriver er TestElement ikke tomt i "save.xml" da der er indsat et linjeskift.


Et kig på Microsoft's dokumentation leder min opmærksomhed hen på: XmlDocument.PreserveWhitespace

http://msdn.microsoft.com/en-us/library/system.xml.xmldocument.preservewhitespace.aspx

Et lille citat:

If PreserveWhitespace is true before Load or LoadXml is called, white space nodes are preserved; otherwise, if this property is false, significant white space is preserved, white space is not.

If PreserveWhitespace is true before Save is called, white space in the document is preserved in the output; otherwise, if this property is false, XmlDocument auto-indents the output.



En lille test viser at output er som forventet hvis du sætter den property til true.
Avatar billede janus_007 Nybegynder
25. februar 2010 - 18:24 #2
Save metoden er den korrekte måde at gemme xml-data på.

Men spørgsmålet er svært at besvare uden du poster dit schema :)
Avatar billede arne_v Ekspert
26. februar 2010 - 03:58 #3
Spørgsmålet har en lang række meget interessante aspekter.

Men er du interesseret i en hurtig løsning, så vælger du bare en anden af Save metoderne, hvor du selv kontrollerer output formatet.

Eksempel:

using System;
using System.IO;
using System.Xml;

namespace E
{
    public class Program
    {
        public static void Main(string[] args)
        {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml("<TestDoc><TestElement></TestElement></TestDoc>");
            //doc.Save(@"C:\save.xml");
            XmlWriterSettings xmlwrtset = new XmlWriterSettings();
            xmlwrtset.OmitXmlDeclaration = true;
            xmlwrtset.Indent = false;
            XmlWriter xmlwrt = XmlWriter.Create(new StreamWriter(@"C:\save.xml"), xmlwrtset);
            doc.Save(xmlwrt);
            xmlwrt.Close();
        }
    }
}
Avatar billede globen Nybegynder
26. februar 2010 - 08:55 #4
mbulow ->

Er det ikke nærmest det modsatte scenarie du tager udgangspunkt i der? Altså hvis man har et element der blot indeholder et whitespace, kan man med PreserveWhitespace property'en styre om det skal udskrives som tomt eller ej.

janus_007 ->

Jeg forstår ikke helt hvordan mit schema kommer ind i dette billede. Jeg validerer om et element (string) har en minimum længde på 1. Det som jeg blev helt paf over, var at jeg kan tage noget valid xml, loade det i et XmlDocument objekt, udskrive det til en fil. Og vupti... INVALID!

Principielt mener jeg det er forkert at metoden manipulerer mit data, med mindre jeg explicit ber den om det!

Nogen der måske deler min holdning? :)
Avatar billede mbulow Nybegynder
26. februar 2010 - 11:55 #5
Der er to sider af sagen med PreserveWhitespace...

Den ene side er når der indlæses Xml den anden er når det gemmes.


Vi er helt enige om hvordan PreserveWhitespace påvirker indlæsningen af Xml. (true: Alle whitespace forbliver intakte)


Den interessante detalje er PreserveWhitespace's inflydelse på doc.Save

Forestil dig at du har indlæst noget Xml hvor der ikke er nogle former for whitespace. (Som du gjorde i dit eget eksempel)

Et efterfølgende kald til doc.Save vil give det problematiske output som du selv fik (Output bliver formateret med en masse autoindentation og linjeskift)

Husker du til gengæld at sætte PreserveWhitespace til true inden kaldet til Save bliver output IKKE formateret.

Prøv selv følgende lille codesnippet:

System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
doc.PreserveWhitespace = true;
doc.LoadXml("<TestDoc><TestElement></TestElement></TestDoc>");
doc.Save("C:\\Temp\\test1.xml");
System.IO.File.WriteAllText("C:\\Temp\\test2.xml", doc.OuterXml);


Indholdet af test1.xml og test2.xml skulle meget gerne være identisk
Avatar billede janus_007 Nybegynder
26. februar 2010 - 18:32 #6
Hvordan validerer du at der er en værdi?
Avatar billede arne_v Ekspert
26. april 2010 - 03:47 #7
Tid at få afsluttet her ?
Avatar billede globen Nybegynder
30. november 2010 - 12:44 #8
Det er nu ½ år siden jeg har logget på eksperten, og jeg havde glemt alt om dette spørgsmål. Unskyld! Det er ikke pænt gjort over for sådan nogle behjælpelige sjæle som jer.

Mbulow & arne, jeg har 200pts up for grabs til jer.
Avatar billede arne_v Ekspert
30. november 2010 - 15:04 #9
svar fra mig
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester