Validering av XML
Råmaterialet er beskevet i modulen Noen datasett, og har denne strukturen
<?xml version="1.0" encoding="ISO-8859-1"?>
<IOC>
<OlympicGame place="Barcelona" year="1992">
<event dist="100m">
<athlet>
<name>Dennis Mitchell</name>
<nation>USA</nation>
<result>10.04</result>
</athlet>
...
</event>
...
</OlympicGame>
...
</IOC>
I sin helhet: all_results.xml
Hvem er hvem
Vi ønsker å lage en liste av deltagere (athlets) der hver deltager er representert kun en gang. Vi baserer oss da på at navnet er god nok identifikasjon. Koden for å etablere lista og finne en deltagers deltagelse blir slik:
// adding name of athlets to listbox
private void buttonAthlets_Click(object sender, EventArgs e)
{
if (m_Doc == null) { return; }
XmlNodeList alist = m_Doc.SelectNodes("//name");
foreach (XmlElement aelt in alist)
{
String nText = aelt.InnerText;
// already there ?
if (listBoxSelection.Items.IndexOf(nText) == -1)
listBoxSelection.Items.Add(nText);
}
}
// selecting an athletname, report all performances
private void listBoxSelection_SelectedIndexChanged(object sender, EventArgs e)
{
String t = listBoxSelection.SelectedItem.ToString();
String xpath = String.Format("//athlet[name='{0}']", t);
XmlNodeList same = m_Doc.SelectNodes(xpath);
textBox1.Text = "";
foreach (XmlElement a in same)
{
textBox1.Text += String.Format("{0} i {1} - {2}\r\n",
((XmlElement)a.ParentNode).GetAttribute("dist"),
((XmlElement)a.ParentNode.ParentNode).GetAttribute("place"),
((XmlElement)a.ParentNode.ParentNode).GetAttribute("year"));
}
}
Validering
Vi ønsker å validere fila med resultater. Vi kan gjøre dette på mange måter. Her bruker vi en enkel framgangsmåte:
- last opp XML-fila i Visual Studio
- fra menyen XML, velg Create Schema
- lage denne i prosjektkatalogen
- adder schema-fila til prosjektet
- sørg for at både xml-fila og schema-fila kopieres til den katalogen applikasjonen kjøres
String XSDFILEPATH = Path.Combine(Application.StartupPath, "all_results.xsd"); String XMLFILEPATH = Path.Combine(Application.StartupPath, "all_results.xml");
Følgende kode etablerer XmlDocumentet, viser det i en webbrowser kontrol og validerer.
private void postInitialize()
{
try
{
String filename=Path.Combine(Application.StartupPath,
"all_results.xml");
webBrowser1.Url = new Uri(XMLFILEPATH);
m_Doc = new XmlDocument();
// will fail if malformed or not found
m_Doc.Load(XMLFILEPATH);
m_Doc.Normalize();
// validate
XmlReaderSettings settings = new XmlReaderSettings();
settings.Schemas.Add(null, XSDFILEPATH);
settings.ValidationType = ValidationType.Schema;
settings.ValidationEventHandler +=
new ValidationEventHandler(SchemaValidationEventHandler);
XmlReader rdr =
XmlReader.Create(new StringReader(m_Doc.InnerXml), settings);
while (rdr.Read()) { }
}
catch (Exception ex)
{
webBrowser1.DocumentText =
String.Format(@"<html><body>
<p>Sorry:</p>
<p>{0}</p>
</body></html>", ex.Message);
m_Doc = null;
}
}
Merk metoden SchemaValidationEventHandler som gor oss advarsler ogfeilmeldinger under valideringen.
// pick up validation errors/warnngs
// report in text box
private void SchemaValidationEventHandler(object sender, ValidationEventArgs e)
{
switch (e.Severity)
{
case XmlSeverityType.Error:
textBox1.Text += String.Format("\r\nError: {0}", e.Message);
break;
case XmlSeverityType.Warning:
textBox1.Text += String.Format("\r\nWarning: {0}", e.Message);
break;
}
}
Vi har valgt et enkelt demonstarsjonseksempel, laget schema-fila ukritisk og brukt den uten endringer. I de fleste tilfelle ønsker vi å validere filer som er laget eller importert fra programmer vi ikke har kontroll over. En fornuftig framgangsmåter er trolig å lage en schema-fil basert på et eksempel og deretter editere denne for hånd for å generalisere og eller presisere. Den schema-fila vi får laget i dette eksempelet ser slik ut:
<?xml version="1.0" encoding="iso-8859-1"?>
<xs:schema attributeFormDefault="unqualified"
elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="IOC">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="OlympicGame">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="event">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="athlet">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string" />
<xs:element name="nation" type="xs:string" />
<xs:element name="result" type="xs:decimal" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="dist" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="place" type="xs:string" use="required" />
<xs:attribute name="year" type="xs:unsignedShort" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
For å kunne bearbeide denne må vi sette oss inn hvordan xsd-filer er bygget opp. Vi forfølger ikke dette her, men det er mye å hente både i presisering av lovlige verdirer og i generalisering av hvordan validerbare filer kan bygges opp. Er det f.eks. viktig at elementene name, nation,result kommer i nøyaktig den rekkefølgen ? En modifisert versjon kan se slik ut:
Koden i Formen er i sin helhet slik:
Enkelt valideringseksempel
Et enkelt eksempel som gjør det lett å eksperimentere med schemaer og validering. Eksempelet er bygget rundt de samme dataene som over, men programmet gjør ikke annet enn å laste en XML-fil og validere den.
Koden i Formen er i sin helhet slik:
Du kan lett bytte ut eller endre innholdet i de to filene: results.xml og schema.xsd, eller du kan ganske enkelt endre adressen i formen.





