(MSXML) Validierung bringt falsche Fehlermeldungen

13/05/2008 - 10:03 von marcus ohm | Report spam
Hallo zusammen,

ich habe folgendes Problem mit der Validierung von XML-Dateien anhand eines
XML-Schema.

Mein Ziel ist es in Visual C++ (MFC8, VS2005 SP1) XML-Dateien bzw.
XML-Strings einzulesen und auf Wohlgeformtheit zu überprüfen. Dafür gibt es
zwei Möglichkeiten, die sich in ihrem Verhalten allerdings stark
unterscheiden.

1.Möglichkeit:

- XML Dokument erzeugen
HRESULT
hr=CoCreateInstance(__uuidof(DOMDocument40),NULL,CLSCTX_INPROC_SERVER, __uuidof(IXMLDOMDocument2), (void**)&pIXMLDOMDocument2);

- XML-Dokument auf das Validieren wàhrend des Ladens einstellen und Datein
laden

pIXMLDOMDocument2->put_validateOnParse(VARIANT_TRUE);
pIXMLDOMDocument2->put_resolveExternals(VARIANT_TRUE);
pIXMLDOMDocument2->put_preserveWhiteSpace(VARIANT_TRUE);
hr=pIXMLDOMDocument2->load(_variant_t( strFilename), &sResult);

Ergebnis: Diese Methode validiert korrekt wàhrend des Einlesens der Datei.
Treten Fehler auf werden sie auch korrekt angegeben.

2. Möglichkeit:

- erzeugen eines XML-Dokuments anhand eines Strings mit Hilfe der Methode
loadXML()


IXMLDOMDocument2 *pParserTest=NULL;

hr=CoCreateInstance(__uuidof(DOMDocument40),NULL,CLSCTX_INPROC_SERVER, __uuidof(IXMLDOMDocument2), (void**)&pParserTest);
pParserTest->put_resolveExternals(VARIANT_TRUE);
pIXMLDOMDocument2->put_validateOnParse(VARIANT_FALSE);
pParserTest->put_preserveWhiteSpace(VARIANT_TRUE);

hr = pParserTest->loadXML(xmlString, &sResult);

- in diesem Fall wird nun die Methode validate() explizit aufgerufen
hr=pParserTest->validate(&pParserError);

Ergebnis:
Ist die XML-Datei wohlgeformt, bekomme ich das Resultat S_OK. Befindet sich
an einer Stelle ein Fehler, so endet die Validierung stets mit der Meldung
"-1072897501 Validate failed because the document does not contain exactly
one root node. "

Diese Fehlermeldung ist offensichtlich falsch. Meine Recherche bei Microsoft
hat ergeben, dass dies ein Fehler in der MSXML 3.0 ist; allerdings nur für
die Validierung anhand von DTD's (siehe
http://support.microsoft.com/?scid=...5358&x&y).

Ich verwende in meiner Klasse die msxml2.h und die msxml2.lib. Dummerweise
kann ich daraus nicht ablesen, welche Version der MSXML ich tatsàchlich
verwende (Microsoft hat den Namen der Lib nicht angepasst). Da ich aber mit
dem DOMDocument40 arbeite, schliesse ich mal darauf, dass ich die MSXML4.0
verwende.

Ist jemand von Ihnen mit diesem Problem vertaut und kennt eine Lösung dafür.
Ich benötige beide Methoden, einen XML-Baum zu erzeugen und es ist sehr
unvorteilhaft, wenn eine Methode so fehlerhaft arbeit.

Hier noch das Beispiel-Schema:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:element name="TestElementDef">
<xs:complexType>
<xs:attribute name="requiredAttr" type="xs:integer"
use="required"> </xs:attribute>
<xs:attribute name="optionalAttr" type="xs:string"
use="optional"></xs:attribute>
</xs:complexType>
</xs:element><!-- end element TestElementDef -->

<xs:element name="RootNode"><!-- the one and only RootNode !!! -->
<xs:complexType>

<xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="1"
ref="TestElementDef"/>
</xs:sequence>

</xs:complexType>

<xs:unique name="uniqueRequiredAttr">
<xs:selector xpath="TestElementDef"/>
<xs:field xpath="@requiredAttr"/>
</xs:unique>
</xs:element><!-- end element RootNode -->

</xs:schema>

... und die dazugehörige XML-Datei
<?xml version="1.0" encoding="UTF-8"?>
<RootNode xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="file:/C:/XML/TestSchema.xsd">
<TestElementDef requiredAttr="0"/>
<TestElementDef requiredAttr="0" optionalAttr="opt1"/> <!-- hier ist der
Fehler in der doppelten Vergabe des Wertes für requiredAttr -->
<TestElementDef requiredAttr="5" optionalAttr="opt2"/>
</RootNode>


Ich bedanke mich schon im voraus für Ihre Hilfe.

Grüße
Marcus Ohm
 

Lesen sie die antworten

#1 Martin Honnen
13/05/2008 - 14:04 | Warnen spam
marcus ohm wrote:

2. Möglichkeit:

- erzeugen eines XML-Dokuments anhand eines Strings mit Hilfe der Methode
loadXML()


IXMLDOMDocument2 *pParserTest=NULL;

hr=CoCreateInstance(__uuidof(DOMDocument40),NULL,CLSCTX_INPROC_SERVER, __uuidof(IXMLDOMDocument2), (void**)&pParserTest);
pParserTest->put_resolveExternals(VARIANT_TRUE);
pIXMLDOMDocument2->put_validateOnParse(VARIANT_FALSE);
pParserTest->put_preserveWhiteSpace(VARIANT_TRUE);

hr = pParserTest->loadXML(xmlString, &sResult);

- in diesem Fall wird nun die Methode validate() explizit aufgerufen
hr=pParserTest->validate(&pParserError);



Die validate-Methode wird doch nur benötigt, wenn man das DOM-Dokument
nach dem Laden manipuliert und dann nach vorgenommmenen Änderungen
validieren willst. Ansonsten kannst du auch beim Laden per loadXML
validieren, dazu musst du nur validateOnParse auf true setzen. Und
eventuell die schemas-Kollektion setzen.



Martin Honnen MVP XML
http://JavaScript.FAQTs.com/

Ähnliche fragen