Utvalg fra XML
Versjon 1
Løsningen er basert på etableringen av et XmlDocument:
String xmlsource = "http://www.it.hiof.no/~borres/commondata/olympiade/all_results.xml"; XmlDocument doc=null;
Data lastes og listeboksen med oversikt over olympiader fylles opp:
private void buttonLoad_Click(object sender, EventArgs e) { doc = new XmlDocument(); listBoxOlymp.Items.Clear(); try { doc.Load(xmlsource); labelMsg.Text = "Loaded"; XmlNodeList list = doc.GetElementsByTagName("OlympicGame"); foreach (XmlElement nod in list) listBoxOlymp.Items.Add(new connect(nod)); } catch (Exception ex) { labelMsg.Text = ex.Message; } }
Her er det valgt å lage en egen klasse, connect, som hjelper oss å kople olymiadens navn til XmlElementet som representerer en olympiade. Denne klassen er slik:
// to connect an XMLElement to a listentry class connect { XmlElement elt; public connect(XmlElement elt) {this.elt = elt;} public override string ToString() {return elt.GetAttribute("place");} public XmlElement Elt{get{return elt;}} }
Når brukeren klikker i olympiadelist blir jobben å finne alle deltagerne på 100m i den olympiaden.
private void listBox1_SelectedIndexChanged(object sender, EventArgs e) { // walking the tree, level by level listBoxAthlets.Items.Clear(); connect cnt = (connect)listBoxOlymp.SelectedItem; XmlElement elt = cnt.Elt; XmlNodeList list = elt.GetElementsByTagName("event"); foreach (XmlElement evelt in list) { if (evelt.GetAttribute("dist") == "100m") { XmlNodeList atlist = evelt.GetElementsByTagName("athlet"); foreach (XmlElement at in atlist) listBoxAthlets.Items.Add(at.GetElementsByTagName("name")[0].InnerText); } } }
Alternativt kan vi bruke XPATH til å finne de aktuelle løperne.
private void listBox1_SelectedIndexChanged(object sender, EventArgs e) { // using xpath listBoxAthlets.Items.Clear(); connect cnt = (connect)listBoxOlymp.SelectedItem; XmlElement elt = cnt.Elt; XmlNodeList list =elt.SelectNodes("event[@dist='100m']/athlet"); foreach (XmlElement at in list) listBoxAthlets.Items.Add(at.GetElementsByTagName("name")[0].InnerText); }
Versjon 2
I denne versjonen baserer vi oss på at det kun har vært en olympiade på hvert sted. Det vil si at "place"-attributten entydig identifiserer en olympiade. Med dette utgangspunktet kan vi legge bare olypiade-stedet i lista og så bruke XPATH til å finne 100m-finalistene.
Etableringen av olymiadelista blir slik, uten noe connect-objekt:
private void buttonLoad_Click(object sender, EventArgs e) { doc = new XmlDocument(); listBoxOlympiade.Items.Clear(); try { doc.Load(xmlsource); labelMsg.Text = "Loaded"; XmlNodeList list = doc.SelectNodes("//OlympicGame"); foreach (XmlElement nod in list) listBoxOlympiade.Items.Add(nod.GetAttribute("place")); } catch (Exception ex) { labelMsg.Text = ex.Message; } }
Utvalg av 100m-finalister blir slik:
private void listBox1_SelectedIndexChanged(object sender, EventArgs e) { listBox100m.Items.Clear(); String place=(string)listBoxOlympiade.SelectedItem; String myXpath = String.Format( "//OlympicGame[@place='{0}']/event[@dist='100m']/athlet/name", place ); try { XmlNodeList list = doc.SelectNodes(myXpath); foreach (XmlElement at in list) listBox100m.Items.Add(at.InnerText); } catch (Exception ex) { labelMsg.Text = ex.Message; } }
versjon 3
Vi snur problemet slik at vi begynner med en liste av sprintere som har deltatt i en av de aktuelle olympiadene, for så å finne ut hvor vedkommende har deltatt.
Etableringen av personlista blir slik:
private void buttonLoad_Click(object sender, EventArgs e) { listBox1.Items.Clear(); doc = new XmlDocument(); try { doc.Load(xmlsource); // fill the listbox with names XmlNodeList personer = doc.SelectNodes("//name"); foreach(XmlNode p in personer) { String n=p.InnerText; if (!listBox1.Items.Contains(n)) listBox1.Items.Add(n); } labelMsg.Text = "loaded"; } catch (Exception ex) { labelMsg.Text = ex.Message; } }
Når vi skal velge fra lista kan vi bruke DOM-programmering:
private void listBox1_SelectedIndexChanged(object sender, EventArgs e) { String n = (string)listBox1.SelectedItem; textBoxWhat.Text = n + "\r\n"; XmlNodeList deltagelse = doc.SelectNodes(String.Format("//athlet[name='{0}']",n)); foreach (XmlNode d in deltagelse) { String ovelse = ((XmlElement)d.ParentNode). GetAttribute("dist"); String olymp = ((XmlElement)d.ParentNode.ParentNode). GetAttribute("place"); textBoxWhat.Text += String.Format("deltok på {0} i {1}\r\n",ovelse,olymp); } }
eller vi kan bruke XPATH
private void listBox1_SelectedIndexChanged(object sender, EventArgs e) { String n = (string)listBox1.SelectedItem; textBoxWhat.Text = n + "\r\n"; XmlNodeList deltagelse = doc.SelectNodes(String.Format("//athlet[name='{0}']", n)); foreach (XmlNode d in deltagelse) { String ovelse = ((XmlElement)d.SelectSingleNode("..")). GetAttribute("dist"); String olymp = ((XmlElement)d.SelectSingleNode("../..")). GetAttribute("place"); textBoxWhat.Text += String.Format("deltok på {0} i {1}\r\n", ovelse, olymp); } }