XML Datei mit XmlTextReader lesen
-
@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 ersetzedoc.LoadXml
mitdoc.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
equalsXmlNodeType.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 BeschreibungXmlTextReader.IsEmptyElement
nurtrue
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 nachif (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 nachif (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 statementif (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 herausfilternforeach (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 eingebautrecords.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 fileAus 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-RufnummerIm 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-telefonieDie anderen sind vermutlich ähnliche testnummern
-
@firefly sagte in XML Datei mit XmlTextReader lesen:
Wieso willst du die dann in das e-mail feld deines "FritzRecord" eintragen stattin das entsprechende Telefonnummer feldWeil sie die Struktur eine Mail-Adresse haben. Die TelNummern sind bei mir alles ausschliesslich Ziffern.
Bei diesen Einträgen gibt es nur diese Nummer.
-
@hkdd sagte in XML Datei mit XmlTextReader lesen:
@firefly sagte in XML Datei mit XmlTextReader lesen:
Wieso willst du die dann in das e-mail feld deines "FritzRecord" eintragen stattin das entsprechende Telefonnummer feldWeil sie die Struktur eine Mail-Adresse haben. Die TelNummern sind bei mir alles ausschliesslich Ziffern.
Bei diesen Einträgen gibt es nur diese Nummer.Und da sitzt du einem Missverständnis auf! Wie ich in meinem letzten Post geschrieben habe, ist das eine Spezielle SIP-Rufnummer die nur so aussieht wie eine e-mail addresse aber keine ist!
Wobei SIP-Rufnummer der falsche begriff ist.
Es ist eine SIP Addresse oder URI https://www.placetel.de/ratgeber/sip-adresse- Wie ist eine SIP Adresse aufgebaut?
Der Aufbau einer SIP Adresse beruht auf den Standards für Uniform Resource Identifyer (URI). Diese einheitliche Ressourcenkennung dient der eindeutigen Identifizierung von Ressourcen im World Wide Web.
SIP Adressen können verschiedene Formen annehmen:
Verweis auf eine Webseite (URL – „Uniform Resource Locator“): https://www.placetel.de/ SIP Adresse: sip:123@sip.placetel.com E-Mail-Adresse: mailto:info@placetel.de
Die Syntax einer SIP-Adresse entspricht folgendem Schema:
sip: [User][:Passwort]@[Host][:Port-Nummer][:Parameter][:Header]
Am Anfang der SIP-Adresse steht der Verweis auf das folgende Schema „sip“. Ähnlich einer E-Mail-Adresse steht danach die Kennung des Users, welche aus Buchstaben und Zahlen bestehen kann. Hinter dem @-Zeichen lässt sich der zuständige Host und dessen Domain auslesen.
Die Port-Nummer enthält die Zieladresse der Anfrage, während optionale zusätzliche Parameter oder Header weiterführende Spezifikationen enthalten können.
-
Es geht ja auch etwas um das Anzeigefenster, die Mail-Adressen sind breiter, als die Telefonnummern.
Ich werde in die Überschrift SIP/URI/Mail-Adresse schreiben. Dann ist hoffentlich alles klar.
PS: Du bist ja auch ein Frühaufsteher.