Autor Beitrag
UGrohne
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Veteran
Beiträge: 5502
Erhaltene Danke: 220

Windows 8 , Server 2012
D7 Pro, VS.NET 2012 (C#)
BeitragVerfasst: Di 09.06.09 14:51 
Das ist ein relativ kompliziertes Thema. Folgender Typ XML-Datei soll erstellt werden:
ausblenden XML-Daten
1:
2:
3:
4:
5:
6:
7:
8:
9:
<?xml version="1.0" encoding="UTF-8"?>
/* ... Header... */
<my:sheet xmlns:my="http:///....">
  <my:page>
    <my:client>
      <my:fullname>Testclient</my:fullname>
    </my:client>
  </my:page>
</my:sheet>

Das ist nur ein Auszug, damit die Struktur klar wird. Eigentlich kein großes Problem, aaaaber: Der Header inkl. des Root-Elements (<my:sheet ...>) kommt bei mir als String an, weil dort sehr viele Elemente mit sehr vielen Attributen hinterlegt sind, die in die globale Konfiguration der Software nicht mehr reinpassen (es hat seine Gründe, das ist gegeben ;)). Das erste Element, dass ich erzeuge ist nun <my:page> und dann bis zum Ende.

Im ersten Schritt hatte ich das einfach der String-Konkat zusammengebaut. Mir ist dann allerdings aufgefallen, dass ich ja die Sonderzeichen ersetzen muss und dazu will ich nur ungern eine eigene Methode schreiben. Daher dachte ich an den XML-Writer. Das funktioniert auch, ich kann dem beibringen, den Header zu ignorieren, und das End-Tag des Root-Elements packe ich wieder einfach als String ans Ende. Einwandfrei ... nur, der my-Namespace macht Probleme.

Den Methoden WriteStartElement und WriteElementString kann ich ja ein Prefix für das Element übergeben, dann muss ich aber auch den Namespace übergeben. XmlWriter macht dann zwar ein korrektes XML-Element, allerdings mit einer Namespace-Deklaration als Attribut:
ausblenden XML-Daten
1:
<my:page xmlns:my="WasIchEbenAlsDritterArgumentÜbergebe">					

und damit ist das Dokument nicht mehr brauchbar, weil der Namespace-URI nicht mehr stimmt. Dieser steht ja im Header und ist daher für mich nicht direkt verfügbar.

Gibt es vielleicht in den XML-Klassen irgendwo eine Methode, der ich einen Textstring übergebe und einen String zurückerhalte, in dem die Sonderzeichen ersetzt sind?
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Di 09.06.09 20:25 
Tja, an sowas hat wohl niemand bei MS gedacht ;) . Ich würde den Namespace per Regex entfernen oder mit Reflection mein Glück versuchen, wahrscheinlich XmlTextWriter.AddNamespace.

_________________
>λ=
UGrohne Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Veteran
Beiträge: 5502
Erhaltene Danke: 220

Windows 8 , Server 2012
D7 Pro, VS.NET 2012 (C#)
BeitragVerfasst: Di 09.06.09 21:32 
user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
Tja, an sowas hat wohl niemand bei MS gedacht ;) . Ich würde den Namespace per Regex entfernen oder mit Reflection mein Glück versuchen, wahrscheinlich XmlTextWriter.AddNamespace.

Hmpf. Ich glaub, dann ersetz ich die Zeichen doch lieber selbst per WhiteList :)
UGrohne Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Veteran
Beiträge: 5502
Erhaltene Danke: 220

Windows 8 , Server 2012
D7 Pro, VS.NET 2012 (C#)
BeitragVerfasst: Mi 17.06.09 17:08 
Ich hab mir dazu jetzt mal eine Extension-Method geschrieben und baue das XML wieder von Hand zusammen. Funktioniert theoretisch auch, allerdings ist meine Zeichenersetzung wohl noch nicht ganz ausgereift und ich finde nicht viel Material zu XML in UTF-8-Kodierung.

Folgendes
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
public static string ReplaceXmlSpecialChars(this string me)
        {
            char[] allowed = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
                              'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
                              '0','1','2','3','4','5','6','7','8','9',',',':','-','*','/','&','%',';','!','=','(',')',' '};
            string result = "";
            foreach (char chr in me.ToCharArray())
            {
                if (allowed.Contains(chr))
                    result += chr;
                else
                {
                    byte[] bytes = Encoding.UTF8.GetBytes(new char[] { chr });
                    result += "&#" + bytes[0].ToString() + ";";
                }
            }
            return result;
        }

ersetzt mir die Zeichen korrekt, allerdings scheint der Code nicht korrekt zu sein. Aus einem ü wird hier ein Ã. Ich glaub, ich hab Unicode hier noch nicht kapiert ;). Vielleicht kann mir jemand auf die Sprünge helfen?
danielf
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1012
Erhaltene Danke: 24

Windows XP
C#, Visual Studio
BeitragVerfasst: Mi 17.06.09 17:22 
Hallo,

warum setzt du nicht das Format des XML nicht auf Latin-1 ?

encoding="ISO-8859-1"

Gruß Daniel
JüTho
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2021
Erhaltene Danke: 6

Win XP Prof
C# 2.0 (#D für NET 2.0, dazu Firebird); früher Delphi 5 und Delphi 2005 Pro
BeitragVerfasst: Mi 17.06.09 17:22 
Hallo Uwe,

eine generelle Antwort habe ich nicht. Aber soviel kann ich zu Unicode erläutern: Jedes Unicode-Zeichen besteht aus 1 bis 3 Bytes. Die deutschen Umlaute benötigen 2 Bytes; das 'Ã' ist jeweils das erste davon, du müsstest also bei diesem Verfahren das nachfolgende Byte ebenfalls konvertieren. Aber das ist ja nicht der Sinn der Sache.

Ich glaube, dass es einfach so geht:
ausblenden C#-Quelltext
1:
                   result += "&#" + ((int)chr).ToString() + ";";					

Es muss lediglich der Zahlenwert des betreffenden Zeichens genommen werden.

Übrigens ist "result += " für Strings sehr schlecht: Strings sind unveränderlich; das bedeutet, dass in jedem Durchgang der String komplett neu erzeugt und kopiert werden muss. Das ist nur bei kurzen Strings akzeptabel; bei längeren ist der StringBuilder zu verwenden:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
StringBuilder result = new StringBuilder(me.Length);
...
result.Append(chr);
...
return result.ToString();

Ich dachte, so etwas weißt du; aber vielleicht hast du jetzt nur auf dein Xml-Problem geachtet. Aber wegen anderer Leser wollte ich das nicht so stehenlassen.

Gruß Jürgen
UGrohne Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Veteran
Beiträge: 5502
Erhaltene Danke: 220

Windows 8 , Server 2012
D7 Pro, VS.NET 2012 (C#)
BeitragVerfasst: Mi 17.06.09 18:51 
user profile iconJüTho hat folgendes geschrieben Zum zitierten Posting springen:

Ich glaube, dass es einfach so geht:
ausblenden C#-Quelltext
1:
                   result += "&#" + ((int)chr).ToString() + ";";					

Es muss lediglich der Zahlenwert des betreffenden Zeichens genommen werden.

:autsch: Eigentlich logisch, funktioniert. Danke

user profile iconJüTho hat folgendes geschrieben Zum zitierten Posting springen:
Übrigens ist "result += " für Strings sehr schlecht: Strings sind unveränderlich; das bedeutet, dass in jedem Durchgang der String komplett neu erzeugt und kopiert werden muss. Das ist nur bei kurzen Strings akzeptabel; bei längeren ist der StringBuilder zu verwenden:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
StringBuilder result = new StringBuilder(me.Length);
...
result.Append(chr);
...
return result.ToString();

Ich dachte, so etwas weißt du; aber vielleicht hast du jetzt nur auf dein Xml-Problem geachtet. Aber wegen anderer Leser wollte ich das nicht so stehenlassen.

Ja, das weiß ich, das ist eine Quick & Dirty - Implementation, weil es für das nächste Testing raus musste. Ist aber bereits als ToDo aufgenommen.


user profile icondanielf hat folgendes geschrieben Zum zitierten Posting springen:
warum setzt du nicht das Format des XML nicht auf Latin-1 ?

encoding="ISO-8859-1"

Weil die Applikation, die das nachher verarbeitet, UTF-8 erwartet.