Uploaded image for project: 'Xerces2-J'
  1. Xerces2-J
  2. XERCESJ-1462

When Reusing an XMLGrammarPool and reusing a validating XMLDocumentParser, parsing will fail on consecutive documents using different Schemas

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Reopened
    • Major
    • Resolution: Unresolved
    • 2.10.0
    • None
    • None
    • N/A

    Description

      The issue is triggered with the following sequence :

      • Create an XML11Xonfiguration()
      • Set the config to validating
      • Create an XMLGrammarPoolImpl()
      • Set the "http://apache.org/xml/properties/internal/grammar-pool" to the pool
      • Create a parser with the config
      • Parse a document referring to a schema
      • Parse a second document referring to a different schema, using the same parser

      This will fail, specifying that it cannot find the element.

      The reason is the XMLSchemaValidator findSchemaGrammar() method.

      At line 2632, the GrammarPool, if one is configured, is asked for the schema. The problem is that the fXSDDescription object for a second parse at this point is still identical to what it was at the end of the first parse. In other words, it refers to the schema that was used on the first parse. This schema is retrieved, and the new document is validated against the old schema.

      To fix this, lines 2652 - 2670 should be moved and inserted after line 2629. This ensures that the fXSDDescription is updated with the current schema information before interrogating the GrammarPool.

      ----------------------

      The following test case + xml documents illustrates the issue.

      ====== Test Case Output ======

      Doc 1 Parsed
      :file:/D:/RX/Perforce/arickp_Solor/XDB_10.1/test2.xml:file:/D:/RX/Perforce/arickp_Solor/XDB_10.1/test2.xml:file:/D:/RX/Perforce/arickp_Solor/XDB_10.1/test2.xml:3:44:143:cvc-elt.1.a: Cannot find the declaration of element 'root2'.
      at org.apache.xerces.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:374)
      at org.apache.xerces.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:325)
      at org.apache.xerces.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:282)
      [...]

      ====== Test Case Code ======

      public class ParserTest {

      @Test
      public void testParser() {

      CountingErrorHandler errorHandler = new CountingErrorHandler();
      XMLParserConfiguration parserConfig = new XML11Configuration();
      parserConfig.setErrorHandler(errorHandler);

      XMLDocumentParser parser = new XMLDocumentParser(parserConfig);

      parserConfig.setFeature("http://xml.org/sax/features/validation", true);
      parserConfig.setFeature("http://apache.org/xml/features/validation/schema", true);
      parserConfig.setFeature("http://apache.org/xml/features/validation/schema/normalized-value",
      false);

      XMLGrammarPool pool = new XMLGrammarPoolImpl();
      parserConfig.setProperty("http://apache.org/xml/properties/internal/grammar-pool", pool);

      try

      { File file1 = new File("test1.xml"); URL url1 = file1.toURI().toURL(); XMLInputSource source1 = new XMLInputSource(null, url1.toString(), null); parser.parse(source1); System.out.println("Doc 1 Parsed"); File file2 = new File("test2.xml"); URL url2 = file2.toURI().toURL(); XMLInputSource source2 = new XMLInputSource(null, url2.toString(), null); parser.parse(source2); System.out.println("Doc 2 Parsed"); assertEquals( "Found " + errorHandler.getWarningCount() + " warnings, " + errorHandler.getErrorCount() + " errors, " + errorHandler.getFatalErrorCount() + " fatal errors", 0, errorHandler.getTotalCount()); }

      catch (IOException ioe)

      { ioe.printStackTrace(); fail("Test failed with unexpected IO exception : " + ioe.getMessage()); }

      catch (XNIException xnie)

      { xnie.printStackTrace(); fail("Test failed with unexpected XNI exception : " + xnie.getMessage()); }

      }

      public class CountingErrorHandler implements XMLErrorHandler {

      private int warningCount;
      private int errorCount;
      private int fatalErrorCount;

      @Override
      public void warning(String domain, String key, XMLParseException exception) throws XNIException

      { warningCount++; throw exception; }

      @Override
      public void fatalError(String domain, String key, XMLParseException exception)
      throws XNIException

      { fatalErrorCount++; throw exception; }

      @Override
      public void error(String domain, String key, XMLParseException exception) throws XNIException

      { errorCount++; throw exception; }

      public int getTotalCount()

      { return warningCount + errorCount + fatalErrorCount; }

      public int getWarningCount()

      { return warningCount; }

      public int getErrorCount()

      { return errorCount; }

      public int getFatalErrorCount()

      { return fatalErrorCount; }

      }
      }

      ====== test1.xml ======

      <?xml version="1.0" encoding="UTF-8"?>
      <root1 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation='test1.xsd'>

      <el1>hello</el1>
      <el1>world</el1>
      </root1>

      ====== test1.xsd ======

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

      <xsd:element name="root1">
      <xsd:complexType>
      <xsd:sequence>
      <xsd:element ref="el1" minOccurs='1' maxOccurs='unbounded' />
      </xsd:sequence>
      </xsd:complexType>
      </xsd:element>

      <xsd:element name="el1" type='xsd:string' />

      </xsd:schema>

      ====== test2.xml ======

      <?xml version="1.0" encoding="UTF-8"?>
      <root2 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation='test2.xsd'>

      <el2>hello</el2>
      <el2>world</el2>
      </root2>

      ====== test2.xsd ======

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

      <xsd:element name="root2">
      <xsd:complexType>
      <xsd:sequence>
      <xsd:element ref="el2" minOccurs='1' maxOccurs='unbounded' />
      </xsd:sequence>
      </xsd:complexType>
      </xsd:element>

      <xsd:element name="el2" type='xsd:string' />

      </xsd:schema>

      Attachments

        Activity

          People

            Unassigned Unassigned
            rx Philip Arickx
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated:

              Time Tracking

                Estimated:
                Original Estimate - 0.5h
                0.5h
                Remaining:
                Remaining Estimate - 0.5h
                0.5h
                Logged:
                Time Spent - Not Specified
                Not Specified