Čtení XML souboru   otázka

C#

Zdravím, mám napsanou proceduru na čtení z GPX souboru podle tutoriálu Tomáše Hercega. Všechno mi funguje, ale jen s tímto začátečním tagem:

<?xml version="1.0" encoding="utf-8"?>

<gpx>

Avšak originální GPX má takovýto začáteční tag:

<?xml version="1.0" encoding="utf-8"?>

<gpx xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instanc..." version="1.0" creator="Groundspeak Pocket Query" xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xs... http://www.groundspeak.com/cache/1/0 http://www.groundspeak.com/cache/1/0/cac..." xmlns="http://www.topografix.com/GPX/1/0">

Nevím proč, ale tento druhý příklad mi procedura nechce přečíst. Děkuji za pomoc:-)

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

Jaká procedura? Ke čtení XML se používá XmlDocument a výše uvedený příklad je zcela validní XML s deklarací namespace.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Přesně tato:

foreach (XmlNode n in data.SelectNodes("/gpx/wpt")
{
try { lb.Items.Add(n.SelectSingleNode("name").InnerText); }
catch (Exception ex) { MessageBox.Show(ex.Message); }
}

Kde data je XmlDocument a lb je ListBox

nahlásit spamnahlásit spam 0 odpovědětodpovědět

A co na tom nejede? Hází to chybu? Nepřidá to nic? Prochází to vůbec tím foreach cyklem nebo ho to projde s tím, že nebylo nic nalezené?

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Proběhne to, ale nevypíše to nic. Ani chybu to nevyhodí. Když ale to stejné použiju pro ten druhý soubor kde nejsou atributy u gpx, tak to všechno proběhne jak má. Nevím no, zkoušel jsem to napsat i pro PC a ani tak to nic nedělá. Gpx soubor jsem zkoušel, jestli náhodou není poškozený, ale i navigační soft to bez problému načetl celý.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Odpověď je na MSDN:

If the XPath expression requires namespace resolution, you must use the SelectNodes overload which takes an XmlNamespaceManager as its argument. The XmlNamespaceManager is used to resolve namespaces.

Note If the XPath expression does not include a prefix, it is assumed that the namespace URI is the empty namespace. >>>If your XML includes a default namespace, you must still use the XmlNamespaceManager and add a prefix and namespace URI to it; otherwise, you will not get any nodes selected.<<<

Jinými slovy, musíte použít přetížení metody SelectNodes, které předáte navíc XmlNamespaceManager, kterému lze nastavit, jak se chovat k namespacům.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Díky moc za pomoc:-) Snažím se to nějak dostat do toho čtení a zasekl jsem se u přidání toho NameSpaceManageru. Jestli jsem to dobře pochopil je nutné nacpat do toho NSManageru všechny NameSpace použité v GPX souboru:

XmlNameTable table = new System.Xml.NameTable();
XmlNamespaceManager xnm = new XmlNamespaceManager(table);
xnm.AddNamespace("http://www.w3.org/2001/XMLSchema", "xmlns:xsd");
xnm.AddNamespace("http://www.w3.org/2001/XMLSchema-instance", "xmlns:xsi");
xnm.AddNamespace("http://www.topografix.com/GPX/1/0", "xmlns");

Toto jsou všechny NS z GPX, ale teď co s tím. Snažil jsem se nějak nacpat k XmlDocumentu nové namespace, ale všechny metody vlastnosti jsou pouze GET.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Našel jsem na Microsoftu deklaraci čtení XML za pomoci NamespaceManageru a kód by měl vypadat takto:

XmlNamespaceManager xnm = new XmlNamespaceManager(doc.NameTable);
xnm.AddNamespace("xsd", "http://www.w3.org/2001/XMLSchema");
xnm.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
xnm.AddNamespace("", "http://www.topografix.com/GPX/1/0");

foreach (XmlNode n in doc.SelectNodes("/gpx/wpt", xnm))
{
    Name = n.SelectSingleNodes("name").InnerText;          
}

ale nefunguje to:-D

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Správný zápis. Jen musíte ještě uvnitř dotazu ty namespacy využití podle namespaců, ve kterých opravdu jsou, tedy například:

doc.SelectNodes("/xsd:gpx/xsi:wpt", xnm))

Konkrétní namespacy záleží na tom, jak je to ve zdrojovém souboru.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Jenze samotne elementy v Gpx nemaji pred wpt zadnou "specifikaci"? jako napr "<xsd:wpt>", vsechno je jenom <wpt> nebo <rte>.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Nechápu co myslíte.

Buď je element v defaultním namespacu:

Například: <xsd>

Nebo v pojmenovaném namespacu:

Například: <xsd:wpf>

Defaultní namespace je definován jako:xmlns="namespace"

Pojmenovaný namespace:xmlns:xsd="namespace"

Vy si musíte všechny používané namespacy dostat do XmlNamespaceManager. Klidně všechny jako pojmenované (například n1, n2, n3 atp. - na tom nezáleží). A pak je použijete v dotazu.

Například: /n1:gpx/n2:wpt

Musíte prostě dodržet namespace pod kterým je uvedený prvek v půdodním dokumentu. Podívat se vždycky pod jakým namespacem je uveden - ten dohledáte pomocí jména (buď defaultní nebo pojmenovaný).

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Já právě chápu, že když už nadeklaruji namespace, tak je pak chci využívat. Přikládám ukázku, jak vypadá funkční GPX soubor.

<?xml version="1.0" encoding="utf-8"?>

<gpx xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instanc..." version="1.0" creator="Groundspeak Pocket Query" xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xs... http://www.groundspeak.com/cache/1/0 http://www.groundspeak.com/cache/1/0/cac..." xmlns="http://www.topografix.com/GPX/1/0">

<wpt lat="49,98668" lon="17,000">

<name>Waypoint</name>

<cmt>Komentar</cmt>

</wpt>

</gpx>

A právě tady nikde nejsou ty NS.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

No jsem na tom takhle. Napsal jsem si jednoduchý konzolový prográmek, který by měl vyflusnout 5 řádků textu. Tady je zdroják:

XmlDocument doc = new XmlDocument();
            try
            {
                doc.Load("soubor.gpx");

                XmlNamespaceManager nsm = new XmlNamespaceManager(doc.NameTable);
                nsm.AddNamespace("", "http://www.topografix.com/GPX/1/0");
                nsm.AddNamespace("xsd", "http://www.w3.org/2001/XMLSchema");
                nsm.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");

                Console.WriteLine(doc.SelectSingleNode("desc").InnerText);

                foreach (XmlNode node in doc.SelectNodes("/gpx/wpt", nsm))
                {
                    Console.WriteLine("***************");
                    Console.WriteLine("Name: {0}", node.SelectSingleNode("name").InnerText);
                    Console.WriteLine("Lat: {0}, Lon: {1}", node.Attributes["lat"].Value, node.Attributes["lon"].Value);
                    Console.WriteLine("CMT: {0}", node.SelectSingleNode("cmt").InnerText);
                    Console.WriteLine("***************\n");

                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.StackTrace);
                Console.WriteLine(ex.Message);
            }


            Console.ReadKey();

A takto vypadá soubor, který do toho cpu:

<?xml version="1.0" encoding="utf-8"?>

<gpx xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instanc..." version="1.0" creator="Groundspeak Pocket Query" xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xs... http://www.groundspeak.com/cache/1/0 http://www.groundspeak.com/cache/1/0/cac..." xmlns="http://www.topografix.com/GPX/1/0">

<wpt lat="49.401833" lon="16.784167">

<time>1899-12-30T00:00:00.000</time>

<name><![CDATA[NAME]]></name>

<cmt><![CDATA[Komentar]]></cmt>

<desc></desc>

</wpt>

</gpx>

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Další věc co jsem našel je vytvoření Namespace přes XmlSchema:

XmlSchema schema = new XmlSchema();
schema.Namespaces.Add("", "http://www.topografix.com/GPX/1/0");
doc.Schemas.Add(schema);

Ale ani toto nechodi...

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Ještě mě napadlo, jestli není nutné tam deklarovat NameSpace pro to XML (xmlns:xsd="http://www.w3.org/2001/XMLSchema"), pokud teda to 'ns' za xml znamená NameSpace. Ještě se v Xml moc nevyznám, ale zajímá mě to.

nahlásit spamnahlásit spam 0 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback