Я пытаюсь использовать варианты OLE для проверки XML в Embarcadero C ++ Builder 10.1 Berlin. Моя конечная цель - показать все ошибки валидации вместо первой (следуя этому примеру MSDN ). Мой класс ниже. Когда я запускаю следующую строку, я получаю исключение «Имя свойства недопустимо».
FXmlDomDoc.Exec( XmlFuncSetProperty );
Если я закомментирую эту строку, все будет нормально.
Это создает впечатление, что «MultipleErrorMessages» не является допустимым аргументом для setProperty () в MSXML2.DOMDocument.6.0. Однако, когда я смотрю на список свойств DOM второго уровня , кажется, что это допустимое свойство второго уровня для объекта DOM 6.0 XML.
Что я пробовал:
Определение XmlFuncSetProperty в качестве процедуры вместо функции; та же ошибка.
Установка ValidateOnLoad / ValidateOnParse в false, на случай, если это каким-то образом повлияло на это; та же ошибка.
Переписать класс с помощью _di_IXMLDOMDocument3, _di_IXMLDOMSchemaCollection2, _di_IXMLDOMParseError. Я не смог найти поддержки для нескольких ошибок в этих классах. Я нашел нужные мне функции в нескольких других классах, но они были чисто виртуальными.
Вопросы:
. cpp файл:
//------------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
//------------------------------------------------------------------------------
#include "XmlValidatorU.h"
#include <System.Win.ComObj.hpp>
//------------------------------------------------------------------------------
#pragma package(smart_init)
//------------------------------------------------------------------------------
// Validates XML against Schema
//------------------------------------------------------------------------------
// This class uses OLE objects from MSXML2 to validate XML from an XSD file.
// Generally, use the following steps to deal with OLE objects:
// 1. Define a Variant variable for your OLE Object; assign using CreateOleObject().
// 2. Define your TAutoCmd objects that will be used in Variant.Exec()
// 3. Set TAutoCmd args using << to add settings
// 4. Once everything is set up, call Exec() on your OLE Object variant
// More documentation on OLE objects / TAutoCmd at:
// http://docwiki.embarcadero.com/CodeExamples/Rio/en/AutoCmd_(C%2B%2B)
//------------------------------------------------------------------------------
// This macro clarifies that we're registering OLE Function names to our defined TAutoCmd variables.
//
#define RegisterAutoCmd( _AutoCmd, _OleFunc ) _AutoCmd( _OleFunc )
//------------------------------------------------------------------------------
// These macros clear AutoCmdArgs before setting them.
// I made these because setting an arg multiple times just stacks them up, changing the function signature.
// Then, OLE throws a "Member Not Found" error because it can't find a function with that signature.
//
#define AutoCmdArg( _AutoCmd, _Arg ) _AutoCmd.ClearArgs(); _AutoCmd << _Arg
#define AutoCmdArgs( _AutoCmd, _Arg1, _Arg2 ) AutoCmdArg( _AutoCmd, _Arg1 ); _AutoCmd << _Arg2
//------------------------------------------------------------------------------
__fastcall TXmlValidator::TXmlValidator( String _SchemaLocation )
:
RegisterAutoCmd( CacheProcAdd, "add" ),
RegisterAutoCmd( CacheSetValidateOnLoad, "validateOnLoad" ),
RegisterAutoCmd( XmlProcLoadXml, "loadXML" ),
RegisterAutoCmd( XmlFuncSetProperty, "setProperty" ),
RegisterAutoCmd( XmlSetValidateOnParse, "validateOnParse" ),
RegisterAutoCmd( XmlSetResolveExternals, "resolveExternals" ),
RegisterAutoCmd( XmlSetSchemas, "schemas" ),
RegisterAutoCmd( XmlGetParseError, "parseError" ),
RegisterAutoCmd( ParseErrorGetReason, "reason" )
{
if ( _SchemaLocation.IsEmpty() )
{
FInvalidMsg = "No Schema Location Specified";
}
else if ( ! FileExists( _SchemaLocation ) )
{
FInvalidMsg = "Schema File Does Not Exist: " + _SchemaLocation;
}
else
{
FInvalidMsg = "";
}
if ( FInvalidMsg.Length() > 0 )
{
return;
}
// Instantiate the OLE objects
FSchemaCache = CreateOleObject( "MSXML2.XMLSchemaCache.6.0" );
FXmlDomDoc = CreateOleObject( "MSXML2.DOMDocument.6.0" );
// Set static args that shouldn't change
AutoCmdArg( CacheSetValidateOnLoad, true );
AutoCmdArg( XmlSetValidateOnParse, true );
AutoCmdArg( XmlSetResolveExternals, true );
AutoCmdArgs( XmlFuncSetProperty, "MultipleErrorMessages", true );
const AnsiString NoNameSpace = "";
AutoCmdArgs( CacheProcAdd, NoNameSpace, AnsiString( _SchemaLocation ) );
// Load Cache
FSchemaCache.Exec( CacheSetValidateOnLoad ); // Validate on Load
FSchemaCache.Exec( CacheProcAdd ); // Add Schema file location to the cache
// Now that the cache is loaded, set cached schema as arg to XML
AutoCmdArg( XmlSetSchemas, FSchemaCache );
// Set up Xml Dom doc as much as we can...
FXmlDomDoc.Exec( XmlSetValidateOnParse );
FXmlDomDoc.Exec( XmlSetResolveExternals );
FXmlDomDoc.Exec( XmlSetSchemas );
FXmlDomDoc.Exec( XmlFuncSetProperty );
}
//------------------------------------------------------------------------------
String __fastcall TXmlValidator::ValidationError( String _Xml )
{
if ( FInvalidMsg.Length() > 0 )
{
return FInvalidMsg;
}
AutoCmdArg( XmlProcLoadXml, AnsiString( _Xml ) ); // update the XML for re-parsing
FXmlDomDoc.Exec( XmlProcLoadXml ); // Load the doc from the XML
Variant ParseErr = FXmlDomDoc.Exec( XmlGetParseError ); // Get the parseError object
return ParseErr.Exec( ParseErrorGetReason ); // Extract the reason
}
//------------------------------------------------------------------------------
.h файл:
//------------------------------------------------------------------------------
#ifndef XmlValidatorUH
#define XmlValidatorUH
//------------------------------------------------------------------------------
class PACKAGE TXmlValidator
{
private:
String FInvalidMsg;
// OLE Variant Variables
Variant FSchemaCache;
Variant FXmlDomDoc;
// TAutoCmd Variables
Procedure CacheProcAdd;
PropertySet CacheSetValidateOnLoad;
Procedure XmlProcLoadXml;
Function XmlFuncSetProperty;
PropertySet XmlSetValidateOnParse;
PropertySet XmlSetResolveExternals;
PropertySet XmlSetSchemas;
PropertyGet XmlGetParseError;
PropertyGet ParseErrorGetReason;
public:
__fastcall TXmlValidator( String _SchemaLocation );
String __fastcall ValidationError( String _Xml );
};
//------------------------------------------------------------------------------
#endif