none
kuriose xml einlesen RRS feed

  • Frage

  • Hi,

    ich muss eine kuriose xml einlesen von einem UNIX-System, die nichtmal UTF-8 einhält und Sonderzeichen hat.

    Die passende Klasse, in der die Daten müssen, habe ich schon gebastelt.

    nach welchen Muster kann man sinnvoll eine solche Datei lesen und schreiben?

    Die reale ist natürlich wesentlich größer.

    <?xml version="1.0"?>
    <DATA>
    	<Element Name="p1" Type="Parameter">
    		<Group ID="irgendwas">
    			<Group ID="Parameter">
    				<Property ID="xxxxxx DataType="REAL" Value="0.5555555555" />
    				<Property ID="yyyyy" DataType="USINT" Value="0" />
    			</Group>
    			<Group ID="wasanderes">
    				<Group ID="[0]">
    					<Property ID="Reihenfolge" DataType="USINT" Value="0" />
    					<Property ID="Typ" DataType="STRING" Value="Ø4711" />
    				</Group>
    				<Group ID="[1]">
    					<Property ID="Reihenfolge" DataType="USINT" Value="0" />
    					<Property ID="Typ" DataType="STRING" Value="Ø0815" />
    				</Group>
    				
    			</Group>
    		</Group>
    	</Element>
    </DATA>

    Dienstag, 19. November 2019 08:34

Antworten

  • Hi,

    was meinst Du mit "nach welchem Muster"?

    Wenn Du bereits Klassen hast, die den Aufbau widerspiegeln, deserialisier die Datei bzw. deren XML Inhalt doch einfach!?

    Hilfsmethoden dafür sehen bspw. so aus:

    public class XmlSerializationUtilities
    {
    
        #region Xml Serialization helpers
    
        public static void SerializeObject<T>( string fileName, T data )
        {
            File.WriteAllText( fileName, SerializeObject<T>( data), Encoding.UTF8 );
        }
    
        public static string SerializeObject<T>( T data )
        {
    
            string result = null;
    
            XmlSerializer serializer  = new XmlSerializer( typeof( T ), String.Empty );
            MemoryStream memoryStream = new MemoryStream();
            XmlTextWriter textWriter  = new XmlTextWriter( memoryStream, Encoding.UTF8 );
            textWriter.Indentation = 4;
            textWriter.IndentChar  = ' ';
            textWriter.Formatting  = Formatting.Indented;
    
            XmlSerializerNamespaces xmlNamespace = new XmlSerializerNamespaces();
            xmlNamespace.Add( String.Empty, String.Empty );
    
            serializer.Serialize( textWriter, data, xmlNamespace );
    
            result = Encoding.UTF8.GetString( memoryStream.ToArray() );
    
            textWriter.Close();
            memoryStream.Close();
            memoryStream.Dispose();
    
            return result;
    
        }
    
        public static T DeserializeObject<T>( string fileName )
        {
            return DeserializeString<T>( File.ReadAllText( fileName, Encoding.UTF8 ) );
        }
    
        public static T DeserializeString<T>( string xml )
        {
    
            T result = default(T);
            string xmlContentToParse = null;
            if( xml.StartsWith( "?" ) ) {
                xmlContentToParse = xml.Substring(1);
            } else {
                xmlContentToParse = xml;
            }
    
            XmlSerializer serializer = new XmlSerializer( typeof( T ) );
            StringReader  stringReader = new StringReader( xmlContentToParse );
    
            result = (T)serializer.Deserialize( stringReader );
    
            stringReader.Close();
            stringReader.Dispose();
    
            return result;
    
        }
    
        #endregion
    
    }

    Der Aufruf dann bspw. so:

    DeineRootKlasse x = XmlSerializationUtilities.DeserializeString<DeineRootKlasse>( <VariableMitXmlInhalt> );

    Den Inhalt der Datei kannst Du bspw. mit File.ReadAllText lesen.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
    https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport


    Dienstag, 19. November 2019 08:48
    Moderator
  • Hi,

    ich sehe da keinen Müll. Das ist ein normaler (wenn auch nicht unbedingt sehr schöner und sicherlich verbesserungswürdiger) XML Aufbau.

    Dass die Werte als Attribute und nicht als Inhalt angegeben wurden, stört nicht wirklich. Das kannst Du über die Attribute wie XmlElement, XmlAttribute, XmlText, ... steuern.

    Dasselbe gilt für die Group Elemente. Deine Klassen können auch a, b, c und d heißen aber dennoch auf die Group -> Group -> Group -> ... Elemente zugreifen.

    Sonderzeichen kann man, falls benötigt, vor der Verarbeitung ersetzen und hinterher wieder in den Originalwert zurückstellen.

    Probier's doch einfach mal. Bei Fragen einfach nochmal hier melden.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
    https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport


    Dienstag, 19. November 2019 10:20
    Moderator

Alle Antworten

  • Hi,

    was meinst Du mit "nach welchem Muster"?

    Wenn Du bereits Klassen hast, die den Aufbau widerspiegeln, deserialisier die Datei bzw. deren XML Inhalt doch einfach!?

    Hilfsmethoden dafür sehen bspw. so aus:

    public class XmlSerializationUtilities
    {
    
        #region Xml Serialization helpers
    
        public static void SerializeObject<T>( string fileName, T data )
        {
            File.WriteAllText( fileName, SerializeObject<T>( data), Encoding.UTF8 );
        }
    
        public static string SerializeObject<T>( T data )
        {
    
            string result = null;
    
            XmlSerializer serializer  = new XmlSerializer( typeof( T ), String.Empty );
            MemoryStream memoryStream = new MemoryStream();
            XmlTextWriter textWriter  = new XmlTextWriter( memoryStream, Encoding.UTF8 );
            textWriter.Indentation = 4;
            textWriter.IndentChar  = ' ';
            textWriter.Formatting  = Formatting.Indented;
    
            XmlSerializerNamespaces xmlNamespace = new XmlSerializerNamespaces();
            xmlNamespace.Add( String.Empty, String.Empty );
    
            serializer.Serialize( textWriter, data, xmlNamespace );
    
            result = Encoding.UTF8.GetString( memoryStream.ToArray() );
    
            textWriter.Close();
            memoryStream.Close();
            memoryStream.Dispose();
    
            return result;
    
        }
    
        public static T DeserializeObject<T>( string fileName )
        {
            return DeserializeString<T>( File.ReadAllText( fileName, Encoding.UTF8 ) );
        }
    
        public static T DeserializeString<T>( string xml )
        {
    
            T result = default(T);
            string xmlContentToParse = null;
            if( xml.StartsWith( "?" ) ) {
                xmlContentToParse = xml.Substring(1);
            } else {
                xmlContentToParse = xml;
            }
    
            XmlSerializer serializer = new XmlSerializer( typeof( T ) );
            StringReader  stringReader = new StringReader( xmlContentToParse );
    
            result = (T)serializer.Deserialize( stringReader );
    
            stringReader.Close();
            stringReader.Dispose();
    
            return result;
    
        }
    
        #endregion
    
    }

    Der Aufruf dann bspw. so:

    DeineRootKlasse x = XmlSerializationUtilities.DeserializeString<DeineRootKlasse>( <VariableMitXmlInhalt> );

    Den Inhalt der Datei kannst Du bspw. mit File.ReadAllText lesen.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
    https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport


    Dienstag, 19. November 2019 08:48
    Moderator
  • Hi,

    zum Deserialisieren ist der Müll nicht wirklich geeignet - wie Du siehst hat die xml nur Atrribute, aber kein Value - Value ist hier als Attribut angegeben.

    Ausserdem heißt dann jede Klasse Group.

    Dann gibt es ein Sonderzeichen  "Ø" (Alt+0216)

    MfG


    • Bearbeitet UMorgenw Dienstag, 19. November 2019 09:48
    Dienstag, 19. November 2019 09:33
  • Hi,

    ich sehe da keinen Müll. Das ist ein normaler (wenn auch nicht unbedingt sehr schöner und sicherlich verbesserungswürdiger) XML Aufbau.

    Dass die Werte als Attribute und nicht als Inhalt angegeben wurden, stört nicht wirklich. Das kannst Du über die Attribute wie XmlElement, XmlAttribute, XmlText, ... steuern.

    Dasselbe gilt für die Group Elemente. Deine Klassen können auch a, b, c und d heißen aber dennoch auf die Group -> Group -> Group -> ... Elemente zugreifen.

    Sonderzeichen kann man, falls benötigt, vor der Verarbeitung ersetzen und hinterher wieder in den Originalwert zurückstellen.

    Probier's doch einfach mal. Bei Fragen einfach nochmal hier melden.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
    https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport


    Dienstag, 19. November 2019 10:20
    Moderator
  • Soweit ich das im XML oben erkenne, finden sich hier drei Klassen wieder:

    • Property mit den Attributen ID, DataType und Name jeweils Typ String
    • Group mit dem Attribut ID und den (0 - n vorkommenden) Elementen von Typ Property und Group
    • Element mit den Attributen Name und Type jeweils vom Typ String und dem (0 - n vorkommenden) Element von Typ Group

    Bei deserialisieren kannst du wie oben im Code zu sehen ein Encoding angeben; damit sollte auch das Sonderzeichen zu verarbeiten sein.


    Dienstag, 19. November 2019 10:23
  • das ist nat. nur ein Muster.

    Das Ganze ist 1000 Zeilen lang und mehrfach geschachtelt.

    Wäre eine heiden Arbeit das händisch zu machen, werde es wohl mit Linq2Xml machen :-(

    Ich hatte gehofft man könnte ein paar .net Klassen verbiegen, das was Vernünftiges rauskommt und automatisiert einlesen.

    :-(
    • Bearbeitet UMorgenw Dienstag, 19. November 2019 17:01
    Dienstag, 19. November 2019 17:00