none
XMLTextWriter - Sonderzeichen werden doppelt "escaped" RRS feed

  • Frage

  • Hallo zusammen,

    ich komme eigentlich aus der Ecke Labview und wollte - nachdem die XML Funktionen von Labview ein Graus sind - eine DLL mit den Funktionen die ich benötige in C# (unter Verwendung von Linq to XML) schreiben. Das klappt auch wunderbar nur an der letzten Hürde beisse ich mir die Zähne aus. Im Forum finde ich auch nichts dazu (oder ich bin zu doof den richtigen Suchbegriff für das spezielle Problem einzugeben).

    Das Problem ist wie folgt: Ich möchte ein XML Dokument mit willkürlichem String als Value eines XElements mit Sonderzeichen nach ASCII Encoding escapen (also auch Umlaute wie Ö, Ä oder das scharfe ß). Mein geistreicher String in einem der XElements lautet wörß&'<>"

    Wenn ich diesen escape, erhalte ich jedoch nicht so etwas wie...

    w&#xF6;r&#xDF;&amp;&apos;&lt;&gt;&quot;

    sondern:

    w?r?&amp;amp;&amp;apos;&amp;lt;&amp;gt;&amp;quot;

    Zum einen scheint der Code das Ö und das ß nicht zu erkennen und daher ein ? einzusetzen und zum anderen scheint die Escape funktion mehrfach durchzulaufen, weshalb ein &amp; wiederum in ein &amp;amp; konvertiert wird.

    Nachdem ich hier einfach nicht weiterkomme, bin ich für jeden Tipp dankbar!

    Im folgenden der verwendete (gekürzte) Code meiner DLL. Ich erzeuge die XML Elemente indem ich sie per Linq to XML einem XDocument hinzufüge und letztendlich mit einem XmlTextWriter in eine Datei schreibe.

    public class XMLDocument
    {
            private XDocument document;   // das Dokument wird an anderer Stelle gefüttert        
    
       public XMLDocument(string rootElementName)
            {
                document = new XDocument(new XElement(rootElementName));         
            }        
    
       public void SaveXMLToFileWithEscape (XElement element, string filepath)
            {            
                XmlTextWriter xmlwriter = new XmlTextWriter(filepath, Encoding.ASCII);
                xmlwriter.Formatting = Formatting.Indented;
                document.Save(xmlwriter);
                xmlwriter.Close();        
             }
    }

    Der Rest der Konvertierung klappt wunderbar. Die Tags und Einzüge werden schön erzeugt, lediglich die Sonderzeichen-Konvertierung funktioniert nicht.

    Danke schon einmal im Voraus!!

    Montag, 9. April 2018 09:23

Antworten

Alle Antworten

  • Hallo,

    Du solltest erstmal wissen das ASCII nicht gleich ASCII ist, es gibt unterschiedliche Implementierungen. In .NET ist ASCII mit 7 Bit üblich, oft ist aber ASCII mit 8 Bit üblich. Das musst Du um beding beachten da sonst falsche Ergebnis rauskommen. Ohne wirklichen Grund würde ich nicht mit ASCII arbeiten sondern UTF8 nutzen. Die ersten 128 Zeichen in UTF8 sind identisch mit ASCII 8Bit. UTF8 ist heute auch Standard.

    Schau dir mal diesen Link an, dieser sollte dein Problem lösen


    13 Millionen Schweine landen jährlich im Müll
    Dev Apps von mir: Icon für UWP, UI Strings
    Andere Dev Apps: UWP Community Toolkit Sample App

    Montag, 9. April 2018 10:52
  • Vielen Dank für die schnelle Antwort. Das Encoding habe ich anscheinend total falsch verstanden. Das ergibt jetzt jedenfalls mehr Sinn. Ich dachte, dass sich Encoding in diesem Fall auch auf die Konvertierung der Special Characters auswirkt. Und da ich irgendwo gelesen habe, dass die Umlaute eben nicht in ASCII enthalten waren, hatte ich wohl eine sehr seltsame Art das Thema zu verstehen.

    Mittlerweile habe ich auch die Ursache für die doppelte Ersetzung gefunden. Zum einen hatte ich ein Relikt, das ich übersehen hatte, welches eine zweite Codierung durchgeführt hat. Zum anderen encoded LinqToXML wohl immer (sowohl bei .Save() als auch bei .ToString()) den Ausgabewert. Das klingt soweit erst mal ganz gut, wenn man allerdings auch weitere Sonderzeichen wie Umlaute ersetzen will (Ö, Ä, etc...) und man dafür z.B. die HttpEncode Funktion verwendet, wird auch wieder doppelt konvertiert. Einmal bei der Verwendung von HttpEncode und ein weiteres mal bei document.Save(filepath);

    Gibt es daher eine Möglichkeit ein XDocument so zu speichern (und wenn möglich zusätzlich auch als String auszugeben)bei dem

    A. entweder die Ausgabe des XDocuments als String ohne Escapes durchgeführt wird

    oder

    B. Sowohl Umlaute als auch XML Sonderzeichen auf einen Schlag umgesetzt/gespeichert/ausgegeben werden?

    Oder wie macht ihr das mit den Umlauten?

    Danke!

    Montag, 9. April 2018 12:29
  • Hi,

    so ganz verstehe ich dein Problem nicht. Wenn es etwas zu encoden gibt, macht die Klasse das eigentlich automatisch.

    Wo genau liegt denn dein Problem, wenn Du einfach gar nichts ersetzt, sondern die XML Datei einfach als UTF-8 erstellen lässt?


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community

    Montag, 9. April 2018 13:16
    Moderator
  • Das Problem besteht darin, dass ich nach Vorgabe unserer Schnittstelle auch Umlaute wie z.B. Ö oder Ä oder dergleichen ersetzt haben muss.

    Das kann ich zwar eigentlich mit der WebUitilty.HtmlEncode() Methode lösen, jedoch werden diese Ersetzungen (Ö wird z.B. durch &#214; ersetzt) während des Abspeicherns nicht als Escapezeichen erkannt und wieder ersetzt. Statt &#214; wird dann &amp;#214;

    Montag, 9. April 2018 14:17
  • Hi,

    was willst Du da aus welchem Grund in welcher Form ersetzen?

    Beschreib das bitte genauer.

    Ich sehe keinen Grund, das so zu machen, wenn Du mit UTF-8 arbeitest.

    <?xml version="1.0" encoding="utf-8" standalone="no"?>
    <Irgendwas>
        <Wert>Hallo Wel äöü</Wert>
    </Irgendwas>


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community

    Montag, 9. April 2018 14:42
    Moderator
  • Wenn deine Schnittstelle keine Sonderzeichen will, dann könntest Du so vorgehen

    static void Test()
    {
        System.Xml.XmlDocument xmlDocument = new System.Xml.XmlDocument();
        xmlDocument.LoadXml("<title>wörß</title>");
    
        string text = string.Empty;
    
        using (System.IO.StringWriter sw = new System.IO.StringWriter())
        {
            using (System.Xml.XmlWriter xw = System.Xml.XmlWriter.Create(sw))
            {
                xmlDocument.WriteTo(xw);
                xw.Flush();
                text = sw.GetStringBuilder().ToString();
            }
        }
    
        var enc = WebUtility.HtmlEncode(text);
    
        var file = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "XmlTestFile.txt");
        System.IO.File.WriteAllText(file, enc);
    
    }

    Das Problem ist das Alleinstehende & was so in XML nicht erlaubt ist. Deswegen ist die Ersetzung durch &amp; korrekt. Siehe hier Link


    13 Millionen Schweine landen jährlich im Müll
    Dev Apps von mir: Icon für UWP, UI Strings
    Andere Dev Apps: UWP Community Toolkit Sample App

    Montag, 9. April 2018 17:04