none
XML-Datei lesen, Werte in ein Objekt speichern und XmlElemente definieren. RRS feed

  • Frage

  • Hallo an Allen,

    ich bin Anfänger in C# und habe ein Paar Fragen u.z. ich muss eine XML-Datei lesen und in Objekt speichern. Die Datei sieht so aus:

    <?xml version="1.0" encoding="utf-8"?>
    <TubeCut xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <Part>
        <Parameter>
          <Type>BentTube</Type>
          <Diameter>125</Diameter>
          <WallThickness>12.523</WallThickness>
          <BentRadius>569</BentRadius>
        </Parameter>
      </Part>
    </TubeCut>

    D.h. wenn ein Element z.B. Diameter gelesen wird, muss der Wert in diesem Fall 125 in Variable diameter gespeichert werden. Wert wird gespeichert.

    Und meine Frage ist jetzt, kann mann irgendwie anders die Datei Lesen ohne  die Namen von Elementen zu schreiben wie z.B. "Diameter", "BentRadius" usw. Ich benutze XmlReader. Das Problem besteht darin ich habe mehrere  Kindklassen, und in XML-Datei werden unterschiedliche Daten von unterschiedlichen Klassen gespeichert. Gibt es vielleicht eine optimale Lösung dazu?

    Habe folgendes gemacht:

    Klasse für Lesen:

    public class LoadFromXML
        {
            NumberStyles style;
    
            public LoadFromXML()
            {
                style = NumberStyles.AllowLeadingSign | NumberStyles.AllowDecimalPoint;
    
                ReadXmlFromTube(@"D:\test1.xml");
            }
    
            public void ReadXmlFromTube(string filePath)
            {
                List<XMLFile> file = new List<XMLFile>();
                ArrayList list = new ArrayList();
                List<Tube> tube = new List<Tube>();
    
                BentTube bent = new BentTube();
                OvalTube oval = new OvalTube();
    
                try
                {
                    XmlReader read = XmlReader.Create(filePath);
    
                    while (read.Read())
                    {
                        if (read.NodeType == XmlNodeType.Element)
                        {
                            if (read.Name == "TubeCut")
                            {
                                list.Add(file);
                            }
    
                            if (read.Name == "Part")
                            {
                                list.Add(tube);
                            }
    
                            if (read.Name == "Parameter")
                            {
                                tube.Add(bent);
                            }
                            else
                            {
                                if (read.Name == "Type")
                                {
                                        read.ReadString();
                                        bent.Type = TubeType.BentTube;
                                }
                                else if (read.Name == "Diameter")
                                {
                                    if (read.MoveToContent() != XmlNodeType.None)
                                        bent.Diameter = Convert.ToDouble(read.ReadString());
                                }
                                else if (read.Name == "WallThickness")
                                {
                                    if (read.MoveToContent() != XmlNodeType.None)
                                        bent.WallThickness = Convert.ToDouble(read.ReadString());
                                }
                                else if (read.Name == "BentRadius")
                                {
                                    if (read.MoveToContent() != XmlNodeType.None)
                                        bent.BentRadius = Convert.ToDouble(read.ReadString());
                                }
    
                            }
                        }
                    }
                    read.Close();
                }
      
                catch (Exception ex)
                {
                    Console.Write("Beim Lesen ist ein fehler aufgetreten.");
                }
            }
        }

    Basisklasse:

    [Serializable]
        [XmlRoot("Tube")]
        public class Tube
        {
    
            #region Private Fields
    
            private TubeType m_tubeType;
    
            private double m_wallThickness;
            private double m_diameter;
    
            private PointSet m_leftInnerContour;
            private PointSet m_leftOuterContour;
            private PointSet m_rightInnerContour;
            private PointSet m_rightOuterContour;
    
            #endregion
    
            #region Constructors
    
            /// <summary>
            /// Constructor
            /// </summary>
            public Tube()
            {
                m_tubeType = TubeType.Not_Specified;
                m_diameter = 0.0;
                m_wallThickness = 0.0;
            }
    
            /// <summary>
            /// Constructor
            /// </summary>
            /// <param name="type">Tube typ</param>
            public Tube(TubeType type)
            {
                m_tubeType = type;
                m_diameter = 0.0;
                m_wallThickness = 0.0;
            }
            
            /// <summary>
            /// 
            /// </summary>
            /// <param name="wallThickness">Wall thickness of the tube</param>
            /// <param name="diameter">Diameter in the tube</param>
            public Tube(double wallThickness, double diameter)
            {
                m_tubeType = TubeType.Not_Specified;
                m_wallThickness = wallThickness;
                m_diameter = diameter;
            }
    
            #endregion
    
            #region Accessors
    
            [XmlElement("Type")]
            public TubeType Type
            {
                get { return m_tubeType; }
                set { m_tubeType = value; }
            }
    
            [XmlElement("Diameter")]
            public double Diameter
            {
                get { return m_diameter; }
                set
                {
                    if (value > 0)
                    {
                        m_diameter = value;
                    }
                    else throw new ArgumentException("Value must be > 0", "Diameter");
                }
            }
    
            [XmlElement("WallThickness")]
            public double WallThickness
            {
                get { return m_wallThickness; }
                set
                {
                    if (value > 0)
                    {
                        m_wallThickness = value;
                    }
                    else throw new ArgumentException("Value must be > 0", "Wall Thickness");
                }
            }
    
            [XmlElement("LeftInnerContour")]
            public PointSet LeftInnerContour
            {
                get { return m_leftInnerContour; }
                set { m_leftInnerContour = value; }
            }
    
            [XmlElement("LeftOuterContour")]
            public PointSet LeftOuterContour
            {
                get { return m_leftOuterContour; }
                set { m_leftOuterContour = value; }
            }
    
            [XmlElement("RightInnerContour")]
            public PointSet RightInnerContour
            {
                get { return m_rightInnerContour; }
                set { m_rightInnerContour = value; }
            }
    
            [XmlElement("RightOuterContour")]
            public PointSet RightOuterContour
            {
                get { return m_rightOuterContour; }
                set { m_rightOuterContour = value; }
            }
    
            #endregion
        }

    Kindklasse:

        [XmlRoot("Parameter")]
        public class BentTube : Tube
        {
            #region Private Fields
    
            private double m_bentRadius;
    
            #endregion
    
            #region Constructor
    
            /// <summary>
            /// Constructor
            /// </summary>
            public BentTube()
                : base(0.0, 0.0)
            {
                m_bentRadius = 0.0;
                base.Type = Types.TubeType.BentTube;
            }
    
            public BentTube(double diameter, double wallThickness, double bentRadius)
                : base(diameter, wallThickness)
            {
                m_bentRadius = bentRadius;
                base.Type = Types.TubeType.BentTube;
            }
    
            #endregion
    
            #region Accessors
    
            [XmlElement("BentRadius")]
            public double BentRadius
            {
                get { return m_bentRadius; }
                set { m_bentRadius = value; }
            }
    
            #endregion
        }
    Ich bin für jede Hilfe dankbar.



    • Bearbeitet nigina_1989 Montag, 17. September 2012 20:03
    Montag, 17. September 2012 15:17

Antworten

  • Hi Ningina,

    wenn ich das richtig Verstehe willst du Objekte ( von Typ BentTube, OvalTube usw, die eine Gemeinsame Basisklasse Tube haben),  mit Werten bestücken die in einer XML Datei stehen und diese Werte im Anschluss wider in die XML Datei speichern.

    Kein Problem mit dem Code von Oben.

    Deine Aufrufe würden etwa so aussehen:

    bentTube = XmlSerialisierung.Deserialisieren(bent.xml);

    ovalTube = XmlSerialisierung.Deserialisieren(oval.xml)

    rountTube = XmlSerialisierung.Deserialisieren(rount.xml);

    Dann Objekte bearbeiten und dann Speichern

    XmlSerialisierung.Serialisieren(bentTube, bent.xml);

    XmlSerialisierung.Serialisieren(ovakTube, oval.xml);

    XmlSerialisierung.Serialisieren(rountTube, rount.xml);

    MFG

    Björn

    Dienstag, 18. September 2012 11:19
  • Anhand des Dateinamen ("bend.xml") weist du doch welche Elemente vorhanden sind. (Wenn ich das Richtig verstanden haben.)

    Und ein Objekt mit Datenbestücken kannst du ganz einfach.

    BentTube bentTube;

    bentTube = XmlSerialisierung.Deserialisieren(bent.xml);

    MFG

    Björn

    Dienstag, 18. September 2012 12:33
  • Hi Nigina,

    ließ die mal den Beitrag durch:

    http://social.msdn.microsoft.com/Forums/de-DE/visualcsharpde/thread/65c6371d-fda8-472c-8144-4bcb89d47374

    Und was Stefan da zum Strategie Pattern und zu Unity bzw MEF schreibt.

    Ich denke wenn du bei den Namen der Datei eine klare Zuordnung hast (bent.xml -> BentTube) sollte es mit dem IoC-Container klappen.

    MFG

    Björn

    Mittwoch, 19. September 2012 08:20

Alle Antworten

  • Hi Nigina_1989,

    Objekte kannst du direkt Serialisieren/Deserialisieren schau dir mal das Beispiel an.

    MFG

    Björn

    Dienstag, 18. September 2012 07:57
  • Hallo Palin,

    danke für deine Antwort, aber ich muss XmlReader benutzen. Serialisieren/Deserialisieren geht leider nicht. Die Werte müssen dann richtig gelesen werden und in Objekten wieder gespeichert werden.

    Grüße, Nigina

    Dienstag, 18. September 2012 09:08
  •  aber ich muss XmlReader benutzen. Serialisieren/Deserialisieren geht leider nicht. Die Werte müssen dann richtig gelesen werden und in Objekten wieder gespeichert werden.

    Verstehe ich jetzt nicht. Außer es ist eine Übungsaufgabe in der du den XMLReader benutzen sollst.

    Ansonsten erstelle dir ein Objekt (kann man auch aus der XML Datei als C# Code generierne lassen).

    Deserialisier das XML File in dein Objekt.

    Bearbeite die Werte und Speicher (Serialisiere) das Objekt.

    MFG

    Björn

    Dienstag, 18. September 2012 09:55
  • Das ist leider keine Übungsaufgabe, ich muss XmlParser für ein Projekt schreiben und das muss mit XmlReader gemacht werden. Mein Problem ist jetzt ich habe mehrere Kindklasse in meinem Fall BentTube, OvalTube, RountTube usw. Und in XMl-File werden die Werten von bestimmten klassen gespeichert z.B. ein Xml-File wie bent.xml mit BentTube, ein anderes oval.xml mit OvalTube usw.
    • Bearbeitet nigina_1989 Dienstag, 18. September 2012 10:30
    Dienstag, 18. September 2012 10:28
  • Hi Ningina,

    wenn ich das richtig Verstehe willst du Objekte ( von Typ BentTube, OvalTube usw, die eine Gemeinsame Basisklasse Tube haben),  mit Werten bestücken die in einer XML Datei stehen und diese Werte im Anschluss wider in die XML Datei speichern.

    Kein Problem mit dem Code von Oben.

    Deine Aufrufe würden etwa so aussehen:

    bentTube = XmlSerialisierung.Deserialisieren(bent.xml);

    ovalTube = XmlSerialisierung.Deserialisieren(oval.xml)

    rountTube = XmlSerialisierung.Deserialisieren(rount.xml);

    Dann Objekte bearbeiten und dann Speichern

    XmlSerialisierung.Serialisieren(bentTube, bent.xml);

    XmlSerialisierung.Serialisieren(ovakTube, oval.xml);

    XmlSerialisierung.Serialisieren(rountTube, rount.xml);

    MFG

    Björn

    Dienstag, 18. September 2012 11:19
  • Ja du hast richtig verstanden, ich möchte Objekte mit Werten bestücken, die in einer XML Datei stehen aber dann nicht in XML Datei speichern sondern diese XML Datei lesen und anschließend Objekte mit Werten bestücken.

    Z.B. ich habe XmlReader für Lesen benutz aber um alle Elemente durchzulesen, muss ich die Elementenname jedes mal in Bedingung schreiben und prüfen, ob XML datei solche Elemente enthält oder nicht. Wie in meinem Fall:

     while (read.Read())
                    {
                        if (read.NodeType == XmlNodeType.Element)
                        {
                            if (read.Name == "TubeCut")
                            {
                                list.Add(file);
                            }
    
                            if (read.Name == "Part")
                            {
                                list.Add(tube);
                            }
    
                            if (read.Name == "Parameter")
                            {
                                tube.Add(bent);
                            }
                            else
                            {
                                if (read.Name == "Type")
                                {
                                    read.ReadString();
                                    bent.Type = TubeType.BentTube;
                                }
                                else if (read.Name == "Diameter")
                                {
                                    if (read.MoveToContent() != XmlNodeType.None)
                                        bent.Diameter = Convert.ToDouble(read.ReadString());
                                }
                                else if (read.Name == "WallThickness")
                                {
                                    if (read.MoveToContent() != XmlNodeType.None)
                                        bent.WallThickness = Convert.ToDouble(read.ReadString());
                                }
                                else if (read.Name == "BentRadius")
                                {
                                    if (read.MoveToContent() != XmlNodeType.None)
                                        bent.BentRadius = Convert.ToDouble(read.ReadString());
                                }
    
                            }
                        }
                    }
                    read.Close();

    Ich prüfe jedes mal, ob bestimmte Elemente vorhanden sind. Aber außer diese Elemente habe ich noch viele andere in anderen Klassen, die dann auch gelesen werden müssen. Und ich finde es sinnlos, 100 Bedingungen für jedes Element zu schreiben.

    Hoffe ich konnte mein Problem gut erklären.

     
    Dienstag, 18. September 2012 12:00
  • Anhand des Dateinamen ("bend.xml") weist du doch welche Elemente vorhanden sind. (Wenn ich das Richtig verstanden haben.)

    Und ein Objekt mit Datenbestücken kannst du ganz einfach.

    BentTube bentTube;

    bentTube = XmlSerialisierung.Deserialisieren(bent.xml);

    MFG

    Björn

    Dienstag, 18. September 2012 12:33
  • Hallo Björn,

    was du geschrieben hast funktioniert. Und meine Frage ist jetzt, was muss ich machen, wenn es um 100 Elemente geht. Jede XML Datei enthält verschiedene Elemente und muss ich dann für jedes Element Bedingung machen? Oder gibt es dafür eine andere Lösung?

    Grüße, Nigina

    Mittwoch, 19. September 2012 06:33
  • Hi Nigina,

    ließ die mal den Beitrag durch:

    http://social.msdn.microsoft.com/Forums/de-DE/visualcsharpde/thread/65c6371d-fda8-472c-8144-4bcb89d47374

    Und was Stefan da zum Strategie Pattern und zu Unity bzw MEF schreibt.

    Ich denke wenn du bei den Namen der Datei eine klare Zuordnung hast (bent.xml -> BentTube) sollte es mit dem IoC-Container klappen.

    MFG

    Björn

    Mittwoch, 19. September 2012 08:20
  • Hallo nigina_1989,

    Ich gehe davon aus, dass die Antworten Dir weitergeholfen haben.
    Solltest Du noch "Rückfragen" dazu haben, so gib uns bitte Bescheid.

    Grüße,
    Robert


    Robert Breitenhofer, MICROSOFT   Bitte haben Sie Verständnis dafür, dass im Rahmen dieses Forums, welches auf dem Community-Prinzip Entwickler helfen Entwickler“ beruht, kein technischer Support geleistet werden kann oder sonst welche garantierten Maßnahmen seitens Microsoft zugesichert werden können.

    Freitag, 19. Oktober 2012 14:59
    Moderator