Entwickler-Ecke

IO, XML und Registry - XML gegen XSD validieren


kingdave2nd - Di 23.06.09 18:48
Titel: XML gegen XSD validieren
Hallo zusammen,

ich knabbere den ganzen Tag nun schon an folgendem Problem rum. Ich möchte gerne eine XML Datei gegen XSD validieren. Im folgenden die XML, XSD und den C# Code:

XML:


XML-Daten
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="1.xsd">
  <header>
    <sourceSystemId>518202</sourceSystemId>
    <certificateKey>sdf67t6t65dsf65sdf6556cv565665sdf7sdfsdvc676sdf</certificateKey>
    <creationDateTime>2009-06-10 10:45</creationDateTime>
  </header>
  <method type='enteov6'>
    <action>createComputer</action>
  </method>
  <properties>
    <property name='name'>c1dv146</property>
    <property name='mac'>112233445566</property>
    <property name='ip'>192.168.11.11</property>
    <property name='os'>Windows XP</property>
    <property name='os_architecture'>x86</property>
    <property name='os_edition'>Professional</property>
    <property name='os_language'>de</property>
  </properties>
</root>


XSD:


XML-Daten
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="root" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
  <xs:element name="root" msdata:IsDataSet="true" msdata:Locale="en-US">
    <xs:complexType>
      <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:element name="header">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="sourceSystem" type="xs:string" minOccurs="0" />
              <xs:element name="sourceSystemId" type="xs:string" minOccurs="0" />
              <xs:element name="certificateKey" type="xs:string" minOccurs="0" />
              <xs:element name="creationDateTime" type="xs:string" minOccurs="0" />
            </xs:sequence>
          </xs:complexType>
        </xs:element>
        <xs:element name="method">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="action" type="xs:string" minOccurs="0" msdata:Ordinal="0" />
            </xs:sequence>
            <xs:attribute name="type" type="xs:string" />
          </xs:complexType>
        </xs:element>
        <xs:element name="properties">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="property" nillable="true" minOccurs="0" maxOccurs="unbounded">
                <xs:complexType>
                  <xs:simpleContent msdata:ColumnName="property_Text" msdata:Ordinal="1">
                    <xs:extension base="xs:string">
                      <xs:attribute name="name" type="xs:string" />
                    </xs:extension>
                  </xs:simpleContent>
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:choice>
    </xs:complexType>
  </xs:element>
</xs:schema>


C# Code:


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
        public void Parse()
        {
                //Name of the XMLFile used for the Exception handling
            string xmlFile = "1.xml";
            string xsdFile = "1.xsd";

            try
            {
                XmlReaderSettings settings = new XmlReaderSettings();
                settings.ValidationType = ValidationType.Schema;
                settings.ValidationEventHandler += ValidationEventHandler;

                settings.Schemas.Add(null, XmlReader.Create("1.xsd"));
                XmlDocument doc = new XmlDocument();
                doc.Schemas.Add(null, XmlReader.Create("1.xsd"));
                doc.Validate(ValidationEventHandler);
                doc.Load(xmlFile);

                    //Create the job
                Job j = new Job();
                j.SourceSystem = doc.SelectSingleNode("/root/header/sourceSystem").InnerText;
                j.SourceSystemId = doc.SelectSingleNode("/root/header/sourceSystemId").InnerText;
                j.CertificateKey = doc.SelectSingleNode("/root/header/certificateKey").InnerText;
                j.CreationDateTime = DateTime.Parse(doc.SelectSingleNode("/root/header/creationDateTime").InnerText);
            }
            catch (XmlException xex)
            {
                Console.WriteLine(xex.Message);
                Console.ReadLine();
            }


Ich habe das XML mal manuell unter http://www.xmlvalidation.com/index.php geprüft, soweit alles in Ordnung. In der Zeile


C#-Quelltext
1:
doc.Validate(ValidationEventHandler);                    


erhalte ich die folgende Fehlermeldung:

"Invalid XML document, The document does not have a root element.."

Vielleicht bin ich ja über den Tag hinweg betriebsblind geworden und finde den Fehler morgen früh beim ersten draufschauen, aber ich habe da so meine Zweifel. Freue mich über jede Hilfe

Gruss Dave


JüTho - Di 23.06.09 18:59

Vielleicht solltest du es nicht "root" nennen? Jürgen


Kha - Di 23.06.09 19:11


C#-Quelltext
1:
2:
                doc.Validate(ValidationEventHandler);
                doc.Load(xmlFile);
Denk nochmal scharf über die Reihenfolge nach ;) ...


kingdave2nd - Mi 24.06.09 13:56

Aaaaargh. Ich habs gewusst, das dass irgendso ein Deppenfehler ist. Natürlich muss ich das Doc erst laden, bevor ichs validieren kann. Das ist das Problem, wenn man von XmlTextReader über XmReader bis hin zum XmlDoc alles ausprobiert und irgendwann den Wald vor Bäumen nicht sieht.

Okay, nun habe ich aber das Problem, dass die Validierung nicht stattfindet. Ein korrektes XML lässt sich sauber parsen, aber wenn ich z.B. die Zeile


XML-Daten
1:
<sourceSystemId>518202</sourceSystemId>                    


aus der XML lösche und das programm laufen lasse, landet der Code wie auch ohne Prüfung bei der Zeile


C#-Quelltext
1:
j.SourceSystem = doc.SelectSingleNode("/root/header/sourceSystem").InnerText;                    


in einer "NullReferenceException". Gut, das macht ja auch Sinn , da ja die angegebene Zeile auch nicht existiert. Die Zeile


C#-Quelltext
1:
doc.Validate(ValidationEventHandler);                    


in der ich erwarten würde, das ein eventueller Fehler im XML abgefangen wird, wird im Debug aber einfach übergangen (sprich der ValidationEventHandler wird nicht gefeuert).
Zugegebenermasse befinde ich mit Events und Delegates noch ein wenig auf "Verständniskriegsfuss", ich denke ich gehe da noch irgendwie falsch dran.

Gruss Dave


danielf - Mi 24.06.09 14:13

Hallo,

das liegt daran, dass laut der xsd das Element SourceSystemID auch nicht zwigend vorkommen muss (minOccurs="0").


XML-Daten
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
 <xs:element name="header">
<xs:complexType>   
         <xs:sequence
             <xs:element name="sourceSystem" type="xs:string" minOccurs="0" />
              <xs:element name="sourceSystemId" type="xs:string" minOccurs="0" />
              <xs:element name="certificateKey" type="xs:string" minOccurs="0" />
              <xs:element name="creationDateTime" type="xs:string" minOccurs="0" />               
         </xs:sequence>
   </xs:complexType>   
</xs:element>


Vlt. einfach nochmal das Schema validieren.
Gruß Daniel

Edit: Das root-Element kann durchaus root heißen (wichtig ist nur das Load("...") vor dem Validate(...)


kingdave2nd - Mi 24.06.09 15:36

Hey vielen Dank für die konstruktive Hilfe.

Nun läuft alles wie gewünscht.

Gruss Dave