SAX2 Parser throws an uncaught xercesc_2_7::XMLValid::Codes exception when
setValidationConstraintFatal is on with enclosing xml tags
-------------------------------------------------------------------------------------------------------------------------------------
Key: XERCESC-1601
URL: http://issues.apache.org/jira/browse/XERCESC-1601
Project: Xerces-C++
Type: Bug
Components: Validating Parser (Schema) (Xerces 1.5 or up only)
Versions: 2.7.0
Environment: Xerces 2.7 recompiled locally
Win2K, WinXP, Win2k3
Microsoft Visual Sutudio 7.1 in either debug or release builds
Reporter: Michel Courtine
I implemented a xerces SAX2 parser by following IBM's recommandations in "Make
the most of Xerces-C++" found at:
http://www-128.ibm.com/developerworks/xml/library/x-xercc/
This parser works fine with large and complex files and performs a very good
validation. No complains at all.
Untill we started to use DOM generated files by a Java app that outputs this
kind of xml data:
<Directory xmlns="http://www.rd.bbc.co.uk/dtv/wp4/System42"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1"
xsi:schemaLocation="http://www.rd.bbc.co.uk/dtv/wp4/System42
../schema/system42.xsd">
<ModuleEntry version="1" type="CODE" name="LIBCORE">
</ModuleEntry>
<ModuleEntry version="1" type="CODE" name="LIBPATH">
</ModuleEntry>
<ModuleEntry version="1" type="OPENTV_RESOURCE" name="SYS_ENV">
</ModuleEntry>
<ModuleEntry version="1" type="OPENTV_RESOURCE" name="SERVICE">
</ModuleEntry>
<ServiceInfo version="1" name="singleStreamVideo">
</ServiceInfo>
</Directory>
When we send the following xml, with "self-contained" tags (one-liners) instead
of empty-enclosing tags, no exceptions are thrown and the validation & parsing
are performed correctly.
<Directory xmlns="http://www.rd.bbc.co.uk/dtv/wp4/System42"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1"
xsi:schemaLocation="http://www.rd.bbc.co.uk/dtv/wp4/System42
../schema/system42.xsd">
<ModuleEntry version="1" type="CODE" name="LIBCORE" />
<ModuleEntry version="1" type="CODE" name="LIBPATH" />
<ModuleEntry version="1" type="OPENTV_RESOURCE" name="SYS_ENV" />
<ModuleEntry version="1" type="OPENTV_RESOURCE" name="SERVICE" />
<ServiceInfo version="1" name="singleStreamVideo" />
</Directory>
An other interesting point for you is that when we turn
setValidationConstraintFatal to false or the validation off, the parsing is
performed correctly too.
This definately means to me that the validation considers the xml file as
invalid although both forms are supposed to be valid from an xsd point of view.
(XMLSpy validates both versions against our xsd).
On top of that, probably because because we set setValidationConstraintFatal to
true, the exception is caught internally and fails silently preventing us from
catching it.
Here is the xsd definition of a ModuleEntry:
<xs:element name="ModuleEntry">
<xs:annotation>
<xs:documentation>Module entry
declaration</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attribute name="name" type="xs:string"
use="required"/>
<xs:attribute name="type" use="required">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration
value="DIRECTORY"/>
<xs:enumeration
value="ENVIRONMENT"/>
<xs:enumeration
value="STREAMEVENTS"/>
<xs:enumeration
value="OPENTV_RESOURCE"/>
<xs:enumeration
value="SYS42_RESOURCE"/>
<xs:enumeration
value="PROPRIETARY_RESOURCE"/>
<xs:enumeration value="CODE"/>
<xs:enumeration value="RAW"/>
<xs:enumeration
value="VERSIONED_RAW"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="version" type="xs:unsignedInt"
use="required"/>
</xs:complexType>
</xs:element>
Here are the features we set in the compilers
bool CParseMgr::parse(const char* sFilename, const char *sXsdPath)
{
CXercesInitialiser InitXerces;
m_sFilename = sFilename;
SAX2XMLReader* parser = XMLReaderFactory::createXMLReader();
parser->setFeature(XMLUni::fgSAX2CoreValidation, true);
parser->setFeature(XMLUni::fgSAX2CoreNameSpaces, true);
parser->setFeature(XMLUni::fgXercesSchema, true);
parser->setFeature(XMLUni::fgXercesSchemaFullChecking, true);
parser->setValidationConstraintFatal(true);
string schemaLocation = "http://www.rd.bbc.co.uk/dtv/wp4/System42 ";
char *unixPath = strdup(sXsdPath);
for (size_t i = 0; i < strlen(unixPath) - 1; i++)
if (unixPath[i] == '\\')
unixPath[i] = '/';
schemaLocation += unixPath;
free(unixPath);
parser->setProperty(XMLUni::fgXercesSchemaExternalSchemaLocation,
XMLString::transcode(schemaLocation.c_str()));
parser->setContentHandler(this);
parser->setErrorHandler(this);
try
{
parser->parse(sFilename);
}
catch (const XMLException& e) {
std::string message = m_sFilename + ":XML exception:" +
XMLtoString(e.getMessage());
Logger::StoreError( message.c_str() );
return false;
}
catch (const SAXParseException& e) {
std::string message = m_sFilename + ":SAXParse exception:" +
XMLtoString(e.getMessage());
Logger::StoreError( message.c_str() );
return false;
}
catch (const SAXException& e) {
std::string message = m_sFilename + ":SAX exception:" +
XMLtoString(e.getMessage());
Logger::StoreError( message.c_str() );
return false;
}
catch (...)
{
string msg = m_sFilename + ":Unhandled exception in CParseMgr::parse()";
Logger::StoreError(msg.c_str());
return false;
}
delete parser;
return true;
}
The exception is thrown just after the first occurence of ModuleEntry
(startElement) and before getting into the endElement Handler
Here is a dump of the call stack a few instructions before the exception is
thrown:
> xerces-c_2_7D.dll!120a3580()
xerces-c_2_7D.dll!120a205a()
MSVCRTD.dll!102134ce()
MSVCRTD.dll!102134ce()
xerces-c_2_7D.dll!120b7324()
xerces-c_2_7D.dll!120d545f()
MSVCRTD.dll!10212d73()
MSVCRTD.dll!1020b5c4()
MSVCRTD.dll!10212a14()
MSVCRTD.dll!102129a6()
MSVCRTD.dll!1020e2cf()
kernel32.dll!7c809e2a()
xerces-c_2_7D.dll!120d54e1()
xerces-c_2_7D.dll!12104391()
xerces-c_2_7D.dll!12105e52()
Tests.exe!CParseMgr::parse(const char * sFilename=0x005c0cbc, const
char * sXsdPath=0x005c0ccc) Line 43 + 0x11 C++
Tests.exe!CScrumVTests::TestRandomFile() Line 138 C++
Tests.exe!boost::unit_test::ut_detail::user_tc_method_invoker<CScrumVTests>::operator()()
Line 209 + 0x1c C++
Tests.exe!boost::unit_test::ut_detail::invoker<boost::unit_test::ut_detail::unused>::invoke<boost::unit_test::ut_detail::user_tc_method_invoker<CScrumVTests>
>() Line 56 + 0x14 C++
Tests.exe!boost::unit_test::ut_detail::callback0_impl_t<boost::unit_test::ut_detail::unused,boost::unit_test::ut_detail::user_tc_method_invoker<CScrumVTests>
>::invoke() Line 89 + 0x24 C++
Tests.exe!boost::unit_test::callback0<boost::unit_test::ut_detail::unused>::operator()()
Line 118 + 0x26 C++
Tests.exe!boost::unit_test::`anonymous
namespace'::zero_return_wrapper::operator()() Line 39 + 0x1a C++
Tests.exe!boost::unit_test::ut_detail::invoker<int>::invoke<boost::unit_test::`anonymous
namespace'::zero_return_wrapper>(boost::unit_test::`anonymous-namespace'::zero_return_wrapper
& f={...}) Line 42 + 0x14 C++
Tests.exe!boost::unit_test::ut_detail::callback0_impl_t<int,boost::unit_test::`anonymous
namespace'::zero_return_wrapper>::invoke() Line 89 + 0x20 C++
Tests.exe!boost::unit_test::callback0<int>::operator()() Line 118 +
0x22 C++
Tests.exe!boost::execution_monitor::catch_signals(const
boost::unit_test::callback0<int> & F={...}, bool __formal=false, bool
__formal=false) Line 493 + 0x34 C++
Tests.exe!boost::execution_monitor::execute(const
boost::unit_test::callback0<int> & F={...}, bool catch_system_errors=false, int
timeout=0) Line 225 + 0x14 C++
Tests.exe!boost::unit_test::unit_test_monitor_t::execute_and_translate(const
boost::unit_test::test_case & tc={...}) Line 56 + 0x55 C++
Tests.exe!boost::unit_test::framework_impl::visit(const
boost::unit_test::test_case & tc={...}) Line 100 + 0xf C++
Tests.exe!boost::unit_test::traverse_test_tree(const
boost::unit_test::test_case & tc={...}, boost::unit_test::test_tree_visitor &
V={...}) Line 155 C++
Tests.exe!boost::unit_test::traverse_test_tree(unsigned long id=65536,
boost::unit_test::test_tree_visitor & V={...}) Line 196 + 0x16 C++
Tests.exe!boost::unit_test::traverse_test_tree(const
boost::unit_test::test_suite & suite={...}, boost::unit_test::test_tree_visitor
& V={...}) Line 167 + 0xd C++
Tests.exe!boost::unit_test::traverse_test_tree(unsigned long id=1,
boost::unit_test::test_tree_visitor & V={...}) Line 198 + 0x16 C++
Tests.exe!boost::unit_test::framework::run(unsigned long id=1, bool
continue_test=true) Line 324 + 0xf C++
Tests.exe!main(int argc=1, char * * argv=0x003a3768) Line 49 + 0x9
C++
Tests.exe!mainCRTStartup() Line 259 + 0x19 C
kernel32.dll!7c816d4f()
ntdll.dll!7c915b4f()
kernel32.dll!7c8399f3()
Thanks for your time.
Best Regards
M
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]