Kontynuacja projektu BazaDanychSQLite 1. Tworzymy klasę PlikXml (plik PlikXml.cs) 2. Metoda do zapisu tabeli osób w pliku XML: using Android.App; using Android.Content; using Android.Util; using Org.XmlPull.V1; using System; using System.IO; namespace BazaDanychSQLite { public static class PlikXml { public static void ZapiszOsobyDoPlikuXml(Activity activity, Osoba[] osoby, string nazwaPlikuXml, IFormatProvider formatProvider = null) { if (formatProvider == null) formatProvider = System.Globalization.CultureInfo.InvariantCulture; Stream fos = activity.OpenFileOutput(nazwaPlikuXml, FileCreationMode.Private); //dopisywanie - FileCreationMode.Append IXmlSerializer xml = Xml.NewSerializer(); xml.SetOutput(fos, "UTF-8"); xml.StartDocument("UTF-8", Java.Lang.Boolean.True); xml.SetFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); string ns = null; //namespace xml.StartTag(ns, "Osoby"); xml.Attribute(ns, "length", osoby.Length.ToString(formatProvider)); foreach(Osoba osoba in osoby) { xml.StartTag(ns, "Osoba"); xml.Attribute(ns, "ID", osoba.Id.ToString(formatProvider)); xml.StartTag(ns, "Imie"); //Imie zamiast Imię - problem przy parsowaniu za pomocą DOM xml.Text(osoba.Imię); xml.EndTag(ns, "Imie"); xml.StartTag(ns, "Nazwisko"); xml.Text(osoba.Nazwisko); xml.EndTag(ns, "Nazwisko"); xml.StartTag(ns, "Wiek"); xml.Text(osoba.Wiek.ToString(formatProvider)); xml.EndTag(ns, "Wiek"); xml.StartTag(ns, "NumerTelefonu"); xml.Text(osoba.NumerTelefonu.ToString(formatProvider)); xml.EndTag(ns, "NumerTelefonu"); xml.EndTag(ns, "Osoba"); } xml.EndTag(ns, "Osoby"); xml.EndDocument(); xml.Flush(); fos.Close(); } } } 3. Użycie w funkcji MainActivity.OnCreate: String nazwaPlikuXml = "osoby.xml"; try { PlikXml.zapiszOsobyDoPlikuXml(this, osoby, nazwaPlikuXml); Toast.makeText(getApplicationContext(), "Plik XML został zapisany", Toast.LENGTH_LONG).show(); } catch(IOException exc) { Toast.makeText(getApplicationContext(), "Błąd zapisu do pliku: " + exc.getLocalizedMessage(), Toast.LENGTH_LONG).show(); } catch(Exception exc) { Toast.makeText(getApplicationContext(), "Ogólny błąd: " + exc.getLocalizedMessage(), Toast.LENGTH_LONG).show(); } 4. Sprawdzamy obecność pliku XML Nie zadziała: Menu Tools, Android, Android Device Monitor, zakładka File Explorer, bo bez zrootowanego urządzenia nie mamy dostępu do katalogu /data/data/pl.umk.fizyka.bazadanychsqlite/files/ Zamiast tego uruchamiamy cmd w katalogu c:\Program Files (x86)\Android\android-sdk\platform-tools\ (jeżeli VS było instalowane przed Android-Studio: c:\Users\pk\Xamarin\MonoForAndroid\AndroidSDK\platform-tools) Uwaga! Musi być włączony jeden emulator lub podłączone urządzenie - w przeciwnym przypadku dodatkowe parametry identyfikujące adb shell su ls -l /data/data/BazaDanychSQLite.BazaDanychSQLite/ more /data/data/BazaDanychSQLite.BazaDanychSQLite/files/osoby.xml exit exit ***************** c:\Program Files (x86)\Android\android-sdk\platform-tools>adb shell generic_x86:/ $ su generic_x86:/ # ls -l /data/data/BazaDanychSQLite.BazaDanychSQLite/ total 32 drwxrwx--x 2 u0_a88 u0_a88 4096 2018-12-30 02:09 cache drwxrwx--x 2 u0_a88 u0_a88 4096 2018-12-30 02:09 code_cache drwxrwx--x 2 u0_a88 u0_a88 4096 2018-12-30 17:55 databases drwxrwx--x 5 u0_a88 u0_a88 4096 2018-12-30 17:55 files lrwxrwxrwx 1 root root 53 2018-12-30 17:54 lib -> /data/app/BazaDanychSQLite.BazaDanychSQLite-1/lib/x86 generic_x86:/ # more /data/data/BazaDanychSQLite.BazaDanychSQLite/files/osoby.xml Hans Muller 32 564738219 Jean Dupont 50 1230198318 John Smith 20 987654321 generic_x86:/ # ********************* 5. Wczytywanie i parsowanie lokalnego pliku XML: public static Osoba[] CzytajOsobyZPlikuXml(Activity activity, string nazwaPlikuXml) { DocumentBuilderFactory dbf = DocumentBuilderFactory.NewInstance(); //dbf.setIgnoringComments(true); //dbf.setIgnoringElementContentWhitespace(true); //dbf.setValidating(false); DocumentBuilder db = dbf.NewDocumentBuilder(); Stream fis = activity.OpenFileInput(nazwaPlikuXml); //Document d = db.parse(fis); //to UTF-8 nie działa - błąd przy Imię Java.IO.Reader r = new Java.IO.InputStreamReader(fis, "UTF-8"); InputSource _is = new InputSource(r); _is.Encoding = "UTF-8"; //to tak naprawdę nie działa - błąd gdy Imię IDocument d = db.Parse(_is); INodeList węzły = d.GetElementsByTagName("Osoba"); int n = węzły.Length; Osoba[] osoby = new Osoba[n]; for (int i = 0; i < n; ++i) { INode węzeł = węzły.Item(i); string _id = węzeł.Attributes.GetNamedItem("ID").NodeValue; int id = int.Parse(_id); INodeList podwęzły = węzeł.ChildNodes; string imię = ""; string nazwisko = ""; int wiek = -1; int numerTelefonu = -1; for (int j = 0; j < podwęzły.Length; ++j) { INode podwęzeł = podwęzły.Item(j); string nazwaPodwęzła = podwęzeł.NodeName; string wartość = ""; if (podwęzeł.HasChildNodes) wartość = podwęzeł.FirstChild.NodeValue; switch (nazwaPodwęzła) { case "Imie": imię = wartość; break; case "Nazwisko": nazwisko = wartość; break; case "Wiek": wiek = int.Parse(wartość); break; case "NumerTelefonu": numerTelefonu = int.Parse(wartość); break; } } osoby[i] = new Osoba(id, imię, nazwisko, wiek, numerTelefonu); } return osoby; } 6. Testowanie w funkcji MainActivity.OnCreate: try { Osoba[] _osoby = PlikXml.CzytajOsobyZPlikuXml(this, nazwaPlikuXml); pokażOsoby(_osoby); Toast.MakeText(ApplicationContext, "Plik XML został odczytany", ToastLength.Long).Show(); } catch (Org.W3c.Dom.DOMException exc) { Toast.MakeText(ApplicationContext, "Błąd parsowania: " + exc.Message + ", kod: " + exc.Code.ToString(), ToastLength.Long).Show(); } catch (System.Exception exc) { Toast.MakeText(ApplicationContext, "Błąd (" + exc.GetType().Name + "): " + exc.Message, ToastLength.Long).Show(); } 7. Pobieranie pliku z serwera WWW: http://www.fizyka.umk.pl/~jacek/dydaktyka/pum/xamarin/xamarin_android/osoby.xml Modyfikacje w metodzie PlikXml.CzytajOsobyZPlikuXMl: public static Osoba[] CzytajOsobyZPlikuXml(Java.Net.URL url) { DocumentBuilderFactory dbf = DocumentBuilderFactory.NewInstance(); //dbf.setIgnoringComments(true); //dbf.setIgnoringElementContentWhitespace(true); //dbf.setValidating(false); DocumentBuilder db = dbf.NewDocumentBuilder(); Stream _is = url.OpenStream(); <--------------------------------------- tylko tu IDocument d = db.Parse(_is); //to UTF-8 nie działa - błąd przy Imię INodeList węzły = d.GetElementsByTagName("Osoba"); int n = węzły.Length; Osoba[] osoby = new Osoba[n]; for (int i = 0; i < n; ++i) { INode węzeł = węzły.Item(i); string _id = węzeł.Attributes.GetNamedItem("ID").NodeValue; int id = int.Parse(_id); INodeList podwęzły = węzeł.ChildNodes; string imię = ""; string nazwisko = ""; int wiek = -1; int numerTelefonu = -1; for (int j = 0; j < podwęzły.Length; ++j) { INode podwęzeł = podwęzły.Item(j); string nazwaPodwęzła = podwęzeł.NodeName; string wartość = ""; if (podwęzeł.HasChildNodes) wartość = podwęzeł.FirstChild.NodeValue; switch (nazwaPodwęzła) { case "Imie": imię = wartość; break; case "Nazwisko": nazwisko = wartość; break; case "Wiek": wiek = int.Parse(wartość); break; case "NumerTelefonu": numerTelefonu = int.Parse(wartość); break; } } osoby[i] = new Osoba(id, imię, nazwisko, wiek, numerTelefonu); } return osoby; } Uwaga! Operacje sieciowe muszą być od Android 3.0 wykonywane w osobnym wątku. Uwaga! Wymagane uprawnienie: INTERNET Test w MainActivity.onCreate: //plik XML z serwera WWW try { Osoba[] _osoby = null; Java.Lang.Thread thread = new Java.Lang.Thread( () => { try { Java.Net.URL url = new Java.Net.URL(@"http://www.fizyka.umk.pl/~jacek/dydaktyka/pum/xamarin/xamarin_android/osoby.xml"); _osoby = PlikXml.CzytajOsobyZPlikuXml(url); } catch (System.Exception exc) { //osobna obsługa wyjątków w każdym wątku throw new System.Exception("Błąd (" + exc.GetType().Name + "): " + exc.Message, exc); //Toast.MakeText(ApplicationContext, "Błąd (" + exc.GetType().Name + "): " + exc.Message, ToastLength.Long).Show(); } }); thread.Start(); thread.Join(); pokażOsoby(_osoby); //musi być w wątku UI Toast.MakeText(ApplicationContext, "Plik XML został odczytany (URI)", ToastLength.Long).Show(); } catch (System.Exception exc) { Toast.MakeText(ApplicationContext, "Błąd (" + exc.GetType().Name + "): " + exc.Message, ToastLength.Long).Show(); }