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]

Reply via email to