我正在尝试使用OLE Variants在Embarcadero C ++ Builder 10.1 Berlin中进行XML验证。我的最终目标是显示所有验证错误,而不仅仅是第一个(在this MSDN example之后)。我的课在下面。运行以下行时,出现“属性名称无效”的异常。
FXmlDomDoc.Exec( XmlFuncSetProperty );
如果我将这一行注释掉,一切正常。
这似乎使“ MultipleErrorMessages”不是MSXML2.DOMDocument.6.0上setProperty()的有效参数。但是,当我查看the list of Second-Level DOM Properties时,似乎这是6.0 XML DOM对象的有效二级属性。
我尝试过的事情:
问题:
.cpp file:
//------------------------------------------------------------------------------
#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 file:
//------------------------------------------------------------------------------
#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
我正在尝试使用OLE Variants在Embarcadero C ++ Builder 10.1 Berlin中进行XML验证。我的最终目标是显示所有验证错误,而不是仅显示第一个(遵循此MSDN示例)...
您链接到的documentation特别声明: