XML Datei mit XmlTextReader lesen



  • Da meine Fritzbox das Telefonbuch als XML-Datei sichert, bin ich dabei, die Daten auszulesen, um sie mit anderen Telefonbüchern, Adressbüchern, Kontakten aus Outlook und Smartphone abzugleichen.
    Ich habe ein kleines Programm nach der Vorlage
    https://learn.microsoft.com/de-de/troubleshoot/developer/visualstudio/csharp/language-compilers/read-xml-data-from-url
    gemacht.
    Dabei ist mir folgendes aufgefallen.
    XmlNodeType.Element und XmlNodeType.EndElement treten normalerweise bei einer korrketen XML-Datei paarweise auf

    <person>
      <realName>Max Meier</realName>
    </person>
    

    Diese Einträge funktionieren problemlos.
    Es gibt aber auch solche Einträge

    <setup />
    <services />
    

    Bei diesen Einträgen wird <setup als Element gemeldet, der Eintrag /> jedoch nicht als EndElement.
    Es fehlt zur Klammer-AUF die Klammer-ZU.
    Kann man das irgendwie erkennen / abfragen unter Nutzung des XmlTextReader ?

    ------------- <Ergänzung> ---------------
    Ich habe nach eine Lösung gesucht und auch gefunden, sicherlich etwas umständlich.
    Ich lese zunächst die XML-Datei in ein string[]-Array ein.
    Beim Erkennen eines XmlNodeType.Element bekommt man neben dem Namen auch die Zeile und Spalte in der XML-Datei mitgeliefert.
    Nun erstelle ich einen Vergleichsstring "<" + Name + " />" und prüfe, ob dieser an der Position in der Original-XML steht,
    falls JA, kann man das entsprechend behandeln / berücksichtigen und das fehlende XmlNodeType.EndElement Signal auslösen.

                String DsnXML = "FRITZ.Box_Telefonbuch_29.01.23_0902.xml";
                string[] ArrXML = System.IO.File.ReadAllLines(DsnXML, Encoding.Default);
                XmlTextReader reader = new XmlTextReader(DsnXML);
      
                while (reader.Read())
                {
                    switch (reader.NodeType)
                    {
                        case XmlNodeType.Element: 
                            int Zeile = reader.LineNumber;
                            int Spalte = reader.LinePosition;
                            string Vergl = "<" + reader.Name + " />";
    
                            if (ArrXML[Zeile - 1].Substring(Spalte-2).StartsWith(Vergl)) 
                            {
                                Console.WriteLine("<xxx /> gefunden: " + Vergl);
                            }
    

    Folgende Meldung wird protokolliert => <xxx /> gefunden: <setup />



  • Benutze lieber system.xml.xmldocument.load(string filename)
    https://learn.microsoft.com/de-de/dotnet/api/system.xml.xmldocument.load?view=netframework-4.8.1#system-xml-xmldocument-load(system-string)

    zum laden des documents.

    Der text vergleich mit einem xmlnode, wie du es macht ist falsch.
    Du suchst den xmlnode mit dem namen "person" oder "setup" und prüfst dann ob es ein child nodes hat. Wenn ja verarbeitet die childs ansonsten gibt es nichts weiter zu tun



  • @hkdd
    Wenn ich die Doku zu XmlTextReader.IsEmptyElement richtig verstehe müsste das genau das sein was du suchst. Etwas irreführend benannt, aber die Erklärung klingt schon sehr danach:

    true if the current node is an element (NodeType equals XmlNodeType.Element) that ends with />; otherwise, false.



  • @hustbaer sagte in XML Datei mit XmlTextReader lesen:

    @hkdd
    Wenn ich die Doku zu XmlTextReader.IsEmptyElement richtig verstehe müsste das genau das sein was du suchst. Etwas irreführend benannt, aber die Erklärung klingt schon sehr danach:

    true if the current node is an element (NodeType equals XmlNodeType.Element) that ends with />; otherwise, false.

    So verwirrend ist es nicht. Denn <tag></tag> und <tag /> sind äquivalent. Die <tag /> Schreibweise ist nur eine verkürzte version.



  • Zunächst vielen Dank für Euere Antworten.
    Es ist wirklich toll in diesem Forum, dass man hier auf Fragen anteilnehmende Antworten bekommt.

    @firefly
    ich kenne den Aufbau der XML-Datei nicht, ich will ihn analysieren, um die Datei später auszuwerten.
    Deshalb muss ich auch ermitteln, welche Namen und zugehörige Daten es überhaupt gibt und was sich dahinter verbirgt.
    Dazu habe ich in der Fritzbox Beispiele eingerichtet, weil man dort viele Dinge angeben und hinterlegen kann, die man für dein eigentlichen Zweck Name + Telefonnummer gar nicht braucht, die aber für andere, z.B. email-Adresse im Outlook-Adressbuch, braucht - bei Outlook hat dagegen die TelNr keine wirklich Bedeutung. Natürlich gibt es Programme, die XML-Dateien anzeigen - aber ich möchte das selbst machen und die Leseroutinen per C# kennenlernen.

    Bisher habe ich die XML-Datei einfach als Textdatei eingelesen, mir den Aufbau angeschaut und mit einfachen Mitteln die nötigen Daten ausgelesen.
    Die einzelnen Zeilen der XML-Datei habe ich zu einem einzigen String ohne "\n" zusammen gefasst. Diesen GesXML-String durchsuche ich anschliessend nach den für mich relevanten Daten und speichere diese in einem List<>Array

    
            public struct FritzRecord
            {
                public string fName  { get; set; } // Name
                public string fHome  { get; set; } // zu Hause
                public string fMobil { get; set; } // TelNr Mobil
                public string fWork  { get; set; } // TelNr auf Arbeit
                public string fFax   { get; set; } // FaxNr
                public string fEMail { get; set; } // EMail
            }
    
            public List<FritzRecord> fList = new List<FritzRecord>();
    
                :::::::::::::::::
                int GesLen = GesXML.Length;
    
                string RealName = "";
                string HomeNr   = "";
                string MobileNr = "";
                string WorkNr   = "";
                string FaxNr  = "";
                string EMail    = "";
                string AvmHome  = "";
                string AvmWork  = "";
    
                int AnzNamen = 0;
    
                for (int i = 0; i < (GesLen - 30) && GesXML.Substring(i, 12) != "</phonebook>"; i++)
                {
                    if (VerglStr(i, "<contact>")) // neuer Kontakt
                    {
                        RealName = HomeNr = MobileNr = WorkNr = FaxNr = AvmHome = AvmWork = EMail = "";
                    }
    
                    if (VerglStr(i, "<realName>"))
                    {
                        RealName = HoleXML(GesXML, i + 10, "</realName>");
                    }
                    if (VerglStr(i,"type=\"home\" prio=\"") && VerglStr(i + 26,"\">"))
                    {
                        HomeNr = AddTelNr(HomeNr, HoleXML(GesXML, i + 28, "</number>"));
                    }
                    if (VerglStr(i,"type=\"home\" id=\"0\" vanity=\"\" prio=\"") && VerglStr(i + 36,"\">"))
                    {
                        HomeNr = AddTelNr(HomeNr, HoleXML(GesXML, i + 39, "</number>"));
                    }
                    if (VerglStr(i,"type=\"work\" prio=\"") && VerglStr(i + 26,"\">"))
                    {
                        WorkNr = AddTelNr(WorkNr, HoleXML(GesXML, i + 28, "</number>"));
                    }
                    if (VerglStr(i,"type=\"mobile\" prio=\"") && VerglStr(i + 28,"\">"))
                    {
                        MobileNr = AddTelNr(MobileNr, HoleXML(GesXML, i + 30, "</number>"));
                    }
                    if (VerglStr(i,"type=\"fax_work\" prio=\"") && VerglStr(i + 30,"\">"))
                    {
                        FaxNr = AddTelNr(FaxNr, HoleXML(GesXML, i + 32, "</number>"));
                    }
                    if (VerglStr(i,"<email classifier=\"private\" id=\"0\">"))
                    {
                        EMail = AddTelNr(EMail, HoleXML(GesXML, i + 35, "</email>"));
                    }
                    if (VerglStr(i,"<number prio=\"1\" type=\"home\" quickdial=\"") && VerglStr(i + 49,"\">"))
                    {
                        AvmHome = AddTelNr(AvmHome, HoleXML(GesXML, i + 51, "</number>"));
                    }
                    if (VerglStr(i,"<number prio=\"1\" type=\"work\" quickdial=\"") && VerglStr(i + 49,"\">"))
                    {
                        AvmWork = AddTelNr(AvmWork, HoleXML(GesXML, i + 51, "</number>"));
                    }
    
                    if (VerglStr(i,"</contact>")) // Ende eines Kontaktes erreicht ?
                    {
                        AnzNamen++;
    
                        if (AvmHome.Length > 0) EMail = AddTelNr(EMail, AvmHome);
                        if (AvmWork.Length > 0) EMail = AddTelNr(EMail, AvmWork);
    
                        fR.fName  = RealName;
                        fR.fHome  = HomeNr;
                        fR.fMobil = MobileNr;
                        fR.fWork  = WorkNr;
                        fR.fFax   = FaxNr;
                        fR.fEMail = EMail;
    
                        fList.Add(fR);
                    }
                } //   for (int i = 0; i < (GesLen - 30) && GesXML.Substring(i, 12) != "</phonebook>"; i++)
    
                SORTfList(); // Nach Namen sortieren
    
                //----------------------------------
                // Sortierte Einträge anzeigen
                //----------------------------------
    
               ::::::::::::::::
    
            static string AddTelNr(string TelNr, string NeueNr) // doppelte anhängen
            {
                if (TelNr.Length > 0) return TelNr + ", " + NeueNr;
                return NeueNr;
            }
    
            //==========================================================
            // In GesXML ab Position idx vergleichen mit VergStr
            //==========================================================
            private bool VerglStr(int idx, string VerglStr) 
            {
                return (GesXML.Substring(idx, VerglStr.Length) == VerglStr);
            }
    
            static string HoleXML(string GesXML, int AnfPos, string EndStr) // Daten auslesen bis Begrenzer
            {
                string rc = "";
                for (int i = AnfPos; i < (GesXML.Length - 30) && GesXML.Substring(i, EndStr.Length) != EndStr; i++)
                {
                    if (GesXML.Substring(i, 4) == "&gt;") // >
                    {
                        rc += ">";
                        i += 3;
                    }
                    else if (GesXML.Substring(i, 4) == "&lt;") // <
                    {
                        rc += "<";
                        i += 3;
                    }
                    else if (GesXML.Substring(i, 5) == "&amp;") // &
                    {
                        rc += "&";
                        i += 4;
                    }
                    else
                        rc += GesXML.Substring(i, 1);
                }
                return rc;
            }
    

    @hustbaer
    das werde ich mir ansehen und benutzen - danke für den Hinweis.

    --------< Ergänzung> ---------

    Es funktioniert einwandfrei.
    Nochmals DANKE !



  • @hkdd sagte in XML Datei mit XmlTextReader lesen:

    Natürlich gibt es Programme, die XML-Dateien anzeigen - aber ich möchte das selbst machen und die Leseroutinen per C# kennenlernen.

    Öhm system.xml.XMLDocument ist eine C# Klasse für das Arbeiten mit XML Dokumenten?
    Also kein "Programm" mit dem man XML Dateien erstellen kann.
    Wobei man die Klasse auch dafür nutzen kann.

    Und was du geschrieben hast ist ein eigener XML Parser. Das solltest du nicht tun!
    Dafür gibt es doch die Klassen im namespace system.xml im .Net Framework!



  • @firefly
    das habe ich ja nun auch so gemacht.
    Ich kann die XML aus meiner Fritzbox auslesen und alle Kontakte anzeigen.



  • @hkdd sagte in XML Datei mit XmlTextReader lesen:

    @firefly
    das habe ich ja nun auch so gemacht.
    Ich kann die XML aus meiner Fritzbox auslesen und alle Kontakte anzeigen.

    Dann hab ich das missverstanden. Denn in deinem vorherigen Post sah es so aus als ob du einen eigenen XML-Parser gebaut hast und den jetzt nutzt statt die Klassen aus System.XML



  • @firefly
    da ich mich zuvor mit XML noch nicht beschäftigt hatte, habe ich halt eine schnelle Lösung gesucht.
    Dann dachte ich, man kann doch die XML-Routinen von C# benutzen und habe das ausprobiert, es klappte auch alles, ausser dem IsEmptyElement, das ich erst dank der Hilfe hier Forum kennen gelernt habe.
    Wenn ich den Codieraufwand vergleiche, dann ist der auch nicht wirklich weniger, als bei meiner eigenen Auswertung der XML-Datei als simple String-Datei. Man kann ja nur mit probieren herausfinden, wo die Daten in der XML-Datei versteckt sind. Wie die FritzBox das macht - darauf hat man keinen Einfluss.
    Hier ein Auszug aus dem Programm

            public struct FritzRecord
            {
                public string fName  { get; set; } // Name
                public string fHome  { get; set; } // zu Hause
                public string fMobil { get; set; } // TelNr Mobil
                public string fWork  { get; set; } // TelNr auf Arbeit
                public string fFax   { get; set; } // FaxNr
                public string fEMail { get; set; } // EMail
            }
    
            public List<FritzRecord> fList = new List<FritzRecord>();
    :::::::::::
            //==============================================
            // Kontakte-XML aus Fritzbox lesen
            //==============================================
            private void mFritzLoad_Click(object sender, EventArgs e)
            {
                fList.Clear();
                FritzRecord fR= new FritzRecord();
    
                OpenFileDialog ofd = new OpenFileDialog();
                ofd.Filter = "XML-Datei (Frizt-Kontakte) (*.xml)|*.xml)";
                ofd.InitialDirectory = ".\\";
                ofd.FileName = "*.xml";
                ofd.RestoreDirectory = true;
    
                if (ofd.ShowDialog() != DialogResult.OK)
                {
                    return; // keine Datei geladen
                }
    
                string XmlDsn = ofd.FileName;
                if (!File.Exists(XmlDsn))
                {
                    MessageBox.Show(
                        "Die Datei " + XmlDsn + " existiert nicht",
                        "Fehlerhafter Dateiname");
                    return;
                }
    
                if (!XmlDsn.ToLower().EndsWith(".xml"))
                {
                    MessageBox.Show(
                        "Die Datei " + XmlDsn + " muss eine XML Datei sein",
                        "Fehlerhafte Datei-Erweiterung");
                    return;
                }
    
                this.Text = "KontakteFritz - Inhalt der Datei " + XmlDsn + " anzeigen";
                XmlTextReader reader = new XmlTextReader(XmlDsn);
    
                string RealName = "";
                string HomeNr   = "";
                string MobileNr = "";
                string WorkNr   = "";
                string FaxNr  = "";
                string EMail    = "";
                string AvmHome  = "";
                string AvmWork  = "";
    
                int AnzNamen = 0;
                string LastElement = "";
    
                while (reader.Read()) // Alle Einträge lesen
                {
                    switch (reader.NodeType) 
                    {
                        //-------------------------
                        case XmlNodeType.Element: // das Element <xxx> oder <xxx a='1' b='2'> oder <xxx />
                        //-------------------------
                            if (reader.IsEmptyElement || !reader.IsStartElement()) break;
                            if (reader.Name == "contact") 
                            {
                                RealName = HomeNr = MobileNr = WorkNr = FaxNr = AvmHome = AvmWork = EMail = "";
                                LastElement= "";
                                break;
                            }
                            LastElement = reader.Name;
                            while (reader.MoveToNextAttribute()) // Lesen der Attribute, falls vorhanden
                            { 
                                LastElement += " " + reader.Name + "='" + reader.Value + "'"; 
                            }
                            break;
                        //-------------------------
                        case XmlNodeType.Text: // Zugehöriger Text zum Element  <xxx>Text</xxx>
                        //-------------------------
                            if (LastElement == "realName") 
                            {
                                RealName = reader.Value;
                                break;
                            }
                            if (LastElement.StartsWith("number type='home'"))
                            {
                                HomeNr = AddTelNr(HomeNr, reader.Value);
                                break;
                            }
                            if (LastElement.StartsWith("number type='work'"))
                            {
                                WorkNr = AddTelNr(WorkNr, reader.Value);
                                break;
                            }
                            if (LastElement.StartsWith("number type='mobile'"))
                            {
                                MobileNr = AddTelNr(MobileNr, reader.Value);
                                break;
                            }
                            if (LastElement.StartsWith("number type='fax_work'"))
                            {
                                FaxNr = AddTelNr(FaxNr, reader.Value);
                                break;
                            }
                            if (LastElement.StartsWith("email"))
                            {
                                EMail = AddTelNr(EMail, reader.Value);
                                break;
                            }
                            if (LastElement.StartsWith("number prio='1' type='home'"))
                            {
                                AvmHome = AddTelNr(AvmHome, reader.Value);
                                break;
                            }
                            if (LastElement.StartsWith("number prio='1' type='work'"))
                            {
                                AvmWork = AddTelNr(AvmWork, reader.Value);
                                break;
                            }
                            break;
                        //-------------------------
                        case XmlNodeType.EndElement: // Das EndElement  </xxx>
                        //-------------------------
                            if (reader.Name == "contact") 
                            {
                                AnzNamen++;
    
                                if (AvmHome.Length > 0) EMail = AddTelNr(EMail, AvmHome);
                                if (AvmWork.Length > 0) EMail = AddTelNr(EMail, AvmWork);
    
                                fR.fName  = RealName;
                                fR.fHome  = HomeNr;
                                fR.fMobil = MobileNr;
                                fR.fWork  = WorkNr;
                                fR.fFax   = FaxNr;
                                fR.fEMail = EMail;
    
                                fList.Add(fR);
                            }
                            break;
                    } // switch (reader.NodeType) 
                } // while (reader.Read()) // Alle Einträge lesen
    
                SORTfList(); // Nach Namen sortieren
    
                //----------------------------------
                // Sortierte Einträge anzeigen
                //----------------------------------
                for (int i = 0; i < fList.Count; i++)
                {
                    //--------------------------------------
                    // Eine Zeile in ListView hinzufügen
                    //--------------------------------------
                    lvi = lvMain.Items.Add(fList[i].fName);
                    lvi.SubItems.Add(fList[i].fHome);
                    lvi.SubItems.Add(fList[i].fWork);
                    lvi.SubItems.Add(fList[i].fMobil);
                    lvi.SubItems.Add(fList[i].fFax);
                    lvi.SubItems.Add(fList[i].fEMail);
                }
            } // mFritzLoad_Click
    
            //================================================================
            // ggf. neuen String an alten anhängen, wenn es mehrere gibt
            //================================================================
            static string AddTelNr(string TelNr, string NeueNr) // doppelte anhängen
            {
                if (TelNr.Length > 0) return TelNr + ", " + NeueNr;
                return NeueNr;
            }
    
            //===========================================
            // List<fList> nach Namen sortieren
            //===========================================
            private void SORTfList()
            {
                FritzRecord zw = new FritzRecord();
    
                int Anz = fList.Count; // Anzahl Einträge
                if (Anz < 2) return; // gibt es mindestens zwei Einträge ? -> nein, dann kein Sortieren
                for (int i = 0; i < (Anz - 1); i++)
                {
                    int m = i; // Index für den kleinsten Namen
    
                    for (int j = (i + 1); j < Anz; j++)
                    {
                        if (fList[j].fName.CompareTo(fList[m].fName) < 0) // j = neues Minimum ?
                        {
                            m = j;
                        }
                    } // NEXT j
    
                    if (i != m) // neues Minimum ?
                    {
                        zw = fList[m];
                        fList[m] = fList[i];
                        fList[i] = zw;
                    }
                }  // NEXT i
            } // SORTfList
    
    


  • Warum hast du denn die Sortiermethode SORTfList selber geschrieben, anstatt die List<T>.Sort Methode zu benutzen?



  • @hkdd Zum verarbeiten einer XML Datei musst man schon kennen wo was steht was man lesen möchte.
    Und mit xPath kann man dann auch gut nach bestimmten Elementen suchen.
    Hier ein Beispiel. Um eine Datei zu laden ersetze doc.LoadXml mit doc.Load

    using System;
    using System.Xml;
    using System.Collections.Generic;
    
    public class Program
    {
        public struct FritzRecord
        {
            public string fName  { get; set; } // Name
            public string fHome  { get; set; } // zu Hause
            public string fMobil { get; set; } // TelNr Mobil
            public string fWork  { get; set; } // TelNr auf Arbeit
            public string fFax   { get; set; } // FaxNr
            public string fEMail { get; set; } // EMail
        }
        public static void Main()
        {
            
            System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
            doc.LoadXml(@"<?xml version=""1.0"" encoding=""utf-8""?>
    <phonebooks>
    <phonebook><contact><category /><person><realName>AVM Ansage (HD)</realName></person><telephony
    nid=""1""><number prio=""1"" type=""work"" quickdial=""99"" id=""0"">500@hd-telefonie.avm.de</number></telephony><services /><setup /><uniqueid>20</uniqueid></contact><contact><category /><person><realName>HD-Musik</realName></person><telephony
    nid=""1""><number prio=""1"" type=""home"" quickdial=""97"" id=""0"">200@hd-telefonie.avm.de</number></telephony><services /><setup /><uniqueid>21</uniqueid></contact><contact><category /><person><realName>HD-Sprache</realName></person><telephony
    nid=""1""><number prio=""1"" type=""home"" quickdial=""98"" id=""0"">100@hd-telefonie.avm.de</number></telephony><services /><setup /><uniqueid>22</uniqueid></contact><contact><category>0</category><person><realName>Test</realName></person><telephony
    nid=""4""><number type=""home"" quickdial=""1"" vanity=""02"" prio=""1"" id=""0"">priv</number><number
    type=""mobile"" prio=""0"" id=""1"">mobil</number><number type=""work"" prio=""0""
    id=""2"">geschftli</number><number type=""fax_work"" prio=""0"" id=""3"">Fax</number></telephony><services
    nid=""1""><email classifier=""private"" id=""0"">e-mail@bla.de</email></services><setup /><features
    doorphone=""0"" /><mod_time>1675340960</mod_time><uniqueid>24</uniqueid></contact></phonebook>
    </phonebooks>
    ");
            // Select all contacts in the xml document
            XmlNodeList nodeList = doc.DocumentElement.SelectNodes("//contact");
            
            List<FritzRecord> records = new List<FritzRecord>();
            foreach (XmlNode node in nodeList)
            {
                FritzRecord rec = new FritzRecord();
                // Select realName node
                XmlNode personRealName = node.SelectSingleNode("person/realName");
                // Select work numer node
                XmlNode workNumber = node.SelectSingleNode("telephony/number[@type='work']");
                // Select home numer node
                XmlNode homeNumber = node.SelectSingleNode("telephony/number[@type='home']");
                // Select mobil numer node
                XmlNode mobileNumber = node.SelectSingleNode("telephony/number[@type='mobile']");
                // Select fax numer node
                XmlNode fax_workNumber = node.SelectSingleNode("telephony/number[@type='fax_work']");
                // Select email numer node
                XmlNode email = node.SelectSingleNode("services/email");
                if (null != personRealName)
                {
                    rec.fName = personRealName.InnerText;
                }
                if (null != workNumber)
                {
                    rec.fWork = workNumber.InnerText;
                }
                if (null != mobileNumber)
                {
                    rec.fMobil = mobileNumber.InnerText;
                }
                if (null != homeNumber)
                {
                    rec.fHome = homeNumber.InnerText;
                }
                if (null != fax_workNumber)
                {
                    rec.fFax = fax_workNumber.InnerText;
                }
                if (null != email)
                {
                    rec.fEMail = email.InnerText;
                }
                records.Add(rec);
            }
            Console.WriteLine("Found records: "+records.Count);
            foreach (var entry in records)
            {
                Console.WriteLine(String.Format("===Entry\nName: {0}\nHome: {1}\nMobil: {2}\nWork: {3}\nFax: {4}\nEmail: {5}\n", entry.fName, entry.fHome, entry.fMobil, entry.fWork, entry.fFax, entry.fEMail));
            }
        }
    }
    

    Ausgabe

    Found records: 4
    ===Entry
    Name: AVM Ansage (HD)
    Home: 
    Mobil: 
    Work: 500@hd-telefonie.avm.de
    Fax: 
    Email: 
    
    ===Entry
    Name: HD-Musik
    Home: 200@hd-telefonie.avm.de
    Mobil: 
    Work: 
    Fax: 
    Email: 
    
    ===Entry
    Name: HD-Sprache
    Home: 100@hd-telefonie.avm.de
    Mobil: 
    Work: 
    Fax: 
    Email: 
    
    ===Entry
    Name: Test
    Home: priv
    Mobil: mobil
    Work: geschftli
    Fax: Fax
    Email: e-mail@bla.de
    


  • @firefly sagte in XML Datei mit XmlTextReader lesen:

    @hustbaer sagte in XML Datei mit XmlTextReader lesen:

    @hkdd
    Wenn ich die Doku zu XmlTextReader.IsEmptyElement richtig verstehe müsste das genau das sein was du suchst. Etwas irreführend benannt, aber die Erklärung klingt schon sehr danach:

    true if the current node is an element (NodeType equals XmlNodeType.Element) that ends with />; otherwise, false.

    So verwirrend ist es nicht. Denn <tag></tag> und <tag /> sind äquivalent. Die <tag /> Schreibweise ist nur eine verkürzte version.

    <tag></tag> ist aber genau so "empty" wie <tag />, allerdings ist laut Beschreibung XmlTextReader.IsEmptyElement nur true für <tag />. Also ja, doch, verwirrend.



  • @firefly , DANKE für Deine Mühe und das Beispiel.
    Ich habe es mal nachvollzogen - und es klappt so, wie es ist.
    Ich habe in meinen Programmen durch spezielle Abfragen und Test mit der Fritzbox eine Möglichkeit gefunden, die spieziellen Einträge für AVM Ansage (HD) und andere AVM-Einträge dahingehend zu erkennen, dass die number keine Tel-Nr sondern ehen eine eMail-Adresse ist.
    100@hd-telefonie.avm.de usw.
    Deshalb bei mir die Abfrage nach

                     if (LastElement.StartsWith("number prio='1' type='home'"))
                            {
                                AvmHome = AddTelNr(AvmHome, reader.Value);
                                break;
                            }
                            if (LastElement.StartsWith("number prio='1' type='work'"))
                            {
                                AvmWork = AddTelNr(AvmWork, reader.Value);
                                break;
                            }
    

    So sieht es bei keiner echten Tel-Nr aus.
    Das ist aber nur ein Beispiel.



  • @hkdd sagte in XML Datei mit XmlTextReader lesen:

    @firefly , DANKE für Deine Mühe und das Beispiel.
    Ich habe es mal nachvollzogen - und es klappt so, wie es ist.
    Ich habe in meinen Programmen durch spezielle Abfragen und Test mit der Fritzbox eine Möglichkeit gefunden, die spieziellen Einträge für AVM Ansage (HD) und andere AVM-Einträge dahingehend zu erkennen, dass die number keine Tel-Nr sondern ehen eine eMail-Adresse ist.
    100@hd-telefonie.avm.de usw.
    Deshalb bei mir die Abfrage nach

                     if (LastElement.StartsWith("number prio='1' type='home'"))
                            {
                                AvmHome = AddTelNr(AvmHome, reader.Value);
                                break;
                            }
                            if (LastElement.StartsWith("number prio='1' type='work'"))
                            {
                                AvmWork = AddTelNr(AvmWork, reader.Value);
                                break;
                            }
    

    So sieht es bei keiner echten Tel-Nr aus.
    Das ist aber nur ein Beispiel.

    Öhm mit diesen checks filterst du eben nicht die AVM eigenen einträge raus
    <number prio="1" type="home" quickdial="98" id="0">100@hd-telefonie.avm.de</number>
    Hier hast du den gleichen text wie in deinem if statement

                 if (LastElement.StartsWith("number prio='1' type='home'"))
    

    Oder missverstehe ich das was.
    Ansonsten haben die AVM eignen Einträge keinen Wert für <category>
    Und das kann man mit folgender Änderung herausfiltern

            foreach (XmlNode node in nodeList)
            {
                // Check if contact entry has an non empty category item
                XmlNode category = node["category"];
                if (null == category  || !category.HasChildNodes)
                {
                    continue;
                }
    


  • @firefly
    ja, über eine nicht vorhandene <category /> könnte man die AVMs erkennen, ich will sie aber auch anzeigen und die number in der Spalte email eintragen. Bisher werte ich die category gar nicht aus.
    Mit meiner Abfrage erkenne ich noch work und home - beides ist in der XML vorhanden

    <number prio="1" type="home" quickdial="97" id="0">200@hd-telefonie.avm.de</number>
    <number prio="1" type="work" quickdial="99" id="0">500@hd-telefonie.avm.de</number>
    

    @Th69
    ich habe jetzt folgendes eingebaut

    records.Sort(delegate(FritzRecord x,FritzRecord y)
                {
                    return x.fName.CompareTo(y.fName);
                }
    );
    

    Das geht natürlich mit viel weniger Aufwand , als die eigene SORT-Routine.
    DANKE für den Hinweis.



  • @hkdd sagte in XML Datei mit XmlTextReader lesen:

    ja, über eine nicht vorhandene <category /> könnte man die AVMs erkennen, ich will sie aber auch anzeigen und die number in der Spalte email eintragen. Bisher werte ich die category gar nicht aus.
    Mit meiner Abfrage erkenne ich noch work und home - beides ist in der XML vorhanden
    <number prio="1" type="home" quickdial="97" id="0">200@hd-telefonie.avm.de</number>
    <number prio="1" type="work" quickdial="99" id="0">500@hd-telefonie.avm.de</number>

    In meinen Beispielcode werden auch die work/home varianten der speziellen fritzbox telefonnummer erkannt. Wieso meinst du hier eine spezielle Abfrage zu benötigen?

    Du hast da ein großes Missverständnis. Nur weil es wie eine e-mail addresse aussieht muss es aber keine sein.
    Das ist eine Telefonnummer, welcher aber nur funktioniert, wenn eine fritzbox als "Telefonanlage" genutzt wird.

    Du brauchst diese separaten Abfragen nicht, welche auch noch fehleranfällig sind. Besonders da sie einen string vergleich machen.
    Denn sobald das attribut "prio" nicht mehr den Wert 1 hat, geht deine Abfrage ins leere.
    Und die Abfragen gehen auch ins leere, wenn sich die Reihenfolge der Attribute ändert im XML file

    Aus sicht von xml
    ist diese Zeile (der textuellen repräsentatiion von XML)
    <number prio="1" type="home" quickdial="98" id="0">
    identisch zu dieser Zeile
    <number type="home" prio="1" quickdial="98" id="0">



  • @firefly ,
    im Prinzip hast Du Recht, mir ist es bisher noch nicht gelungen in der Fritzbox einen Kontakt einzustellen, bei dem in der XML-Datei

    <number prio="1"
    

    steht. Dort steht immer hinter <number das Attribut type=.

    <number type=
    

    Nur bei den voreingestellten AVM-Nummern (die tatsächlich Spezial-Nummer der Fritzbox sind) gibt es diese Einstellungen.
    Es kann natürlich sein, dass nach einem Firmware-Update oder bei einem neueren Modell der Fritzbox das anders ausschaut.
    Ich habe eine FritzBox 7490 - das ist nicht mehr das allerneueste Modell.
    Diese Nummern sind für mich total unwichtig, es ist nur interessant, dass es sie überhaupt gibt.
    Ich habe gerade mal eine Mail mit Outlook an 200@hd-telefonie.avm.de geschickt, mal sehen, was passiert.
    Zurück gekommen ist die Mail noch nicht.



  • @hkdd sagte in XML Datei mit XmlTextReader lesen:

    @firefly ,
    im Prinzip hast Du Recht, mir ist es bisher noch nicht gelungen in der Fritzbox einen Kontakt einzustellen, bei dem in der XML-Datei

    <number prio="1"
    

    steht. Dort steht immer hinter <number das Attribut type=.

    <number type=
    

    Wie gesagt, verlass dich nicht darauf dass es immer so ist.Du baust dir damit nur einen unnötige Fehlerquelle ein.
    Was soll den dein string vergleich erreichen was mit meinem Beispiel code angeblich nicht möglich sei?



  • @hkdd sagte in XML Datei mit XmlTextReader lesen:

    Diese Nummern sind für mich total unwichtig, es ist nur interessant, dass es sie überhaupt gibt.

    Wieso willst du die dann in das e-mail feld deines "FritzRecord" eintragen statt in das entsprechende Telefonnummer feld, wenn diese Nummern angeblich total unwichtig sind?
    Das ganze widerspricht sich doch.



  • @hkdd sagte in XML Datei mit XmlTextReader lesen:

    Ich habe gerade mal eine Mail mit Outlook an 200@hd-telefonie.avm.de geschickt, mal sehen, was passiert.
    Zurück gekommen ist die Mail noch nicht.

    Naja eventuell kommt was zurück oder das ganze wurde einfach ignoriert.
    Und diese Telefonnummer ist definitiv keine e-mail addresse sondern es ist eine SIP-Rufnummer

    Im Falle von 500@hd-telefonie.avm.de ist es eine testnummer mit der man testen kann ob das SIP Telefon, welches mit der Fritzbox verbunden ist, HD-Telefonie unterstützt.
    https://www.telefonansagen.de/news-zu-telefonansagen/hd-telefonie

    Die anderen sind vermutlich ähnliche testnummern


Log in to reply