Is there a way to instantiate a DOMBuilder and supply it with a pre-parsed
Grammar* for a given schema?

For example, if I have the following XML:

Foo.xml:
========
<Foo xmlns="http://example.com/something";
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
  xsi:schemaLocation="http://example.com/SomeThing ./SomeThing.xsd">

  <!-- Foo content, using elements/types defined in SomeThing.xsd, and
    any other <import>'ed schema/namespaces, etc. -->
</Foo>

Bar.xml:
========
<Bar xmlns="http://example.com/SomeThing";
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
  xsi:schemaLocation="http://example.com/SomeThing ./SomeThing.xsd">

  <!-- Bar content, using elements/types defined in SomeThing.xsd, etc. -->
</Bar>


I would like to have DOMBuilders which parse Foo.xml and Bar.xml be supplied
with a preparsed Grammar for SomeThing.xsd.

This is obviously possible with a single DOMBuilder which is reused:

void ParseFooAndBar(void)
{
  static const XMLCh gLS[] = { chLatin_L, chLatin_S, chNull };
  DOMImplementation *impl =
    DOMImplementationRegistry::getDOMImplementation(gLS);
  DOMBuilder *parser = ((DOMImplementationLS*)impl)->createDOMBuilder(
    DOMImplementationLS::MODE_SYNCHRONOUS, 0);

  parser->setFeature(XMLUni::fgDOMNamespaces, true);
  parser->setFeature(XMLUni::fgXercesSchema, true);
  parser->setFeature(XMLUni::fgXercesSchemaFullChecking, true);
  parser->setFeature(XMLUni::fgDOMValidateIfSchema, true);
  parser->setFeature(XMLUni::fgDOMValidation, true);
  parser->setFeature(XMLUni::fgDOMDatatypeNormalization, true);

  // Here's how SomeThing.xsd would get cached...
  parser->setFeature(XMLUni::fgXercesCacheGrammarFromParse, true);
  parser->setFeature(XMLUni::fgXercesUseCachedGrammarInParse, true);

  XMLErrorHandler errorHandler;
  parser->setErrorHandler(&errorHandler);

  XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument *doc = 0;

  try
  {
    parser->resetDocumentPool();
    doc = parser->parseURI("Foo.xml");  // Should cache SomeThing.xsd
    doc = parser->parseURI("Bar.xml");  // Should re-use SomeThing.xsd
  }

  delete parser;
}


That's all fine and dandy, but is there any way to cache SomeThing.xsd
Without re-using the same DOMBuilder?

void HowDoIDoThat(void)
{
  parser = new XercesDOMParser();
  parser->setValidationScheme(XercesDOMParser::Val_Always);
  parser->setDoNamespaces(true);    // optional
  parser->setDoSchema(true);
  parser->setValidationSchemaFullChecking(true);
  parser->cacheGrammarFromParse(true);
  parser->useCachedGrammarInParse(true);

  // set up error handler, yada yada...

  // Uh... docs say owned by parser.. How do we get it to give us ownership?
  Grammar* someThing = parser->loadGrammar("SomeThing.xsd", Schema, false);

  DOMBuilder* fooParser = <instantiate similar to ParseFooAndBar()>;

  // NOTE: don't want/need to cache anything, just reuse SomeThing.xsd
  fooParser->setFeature(XMLUni::fgXercesCacheGrammarFromParse, false);
  fooParser->setFeature(XMLUni::fgXercesUseCachedGrammarInParse, true); //?

  // How?!?
  fooParser->sureWishThereWasAUseGrammarMethod(
    "http://example.com/SomeThing";, someThing);

  doc = fooParser->parseURI("Foo.xml");  // Use SomeThing.xsd... please?

  // Do it again for Bar (desire to use *a new DOMBuilder instance*).
  DOMBuilder* barParser = <same>;

  // <repeat...>

  delete fooParser;
  delete barParser;

  // Assume memory management for 'parser', 'someThing' Grammar etc. is
  // taken care of appropriately...
}


If the above is not possible, what are my options?  Given the nature of my
system, I don't want to take the memory hit of caching *everything*, but
SomeThing.xsd is used in *every* XML file, so I'd like the performance gains
of caching it (memory hit for caching SomeThing.xsd is acceptable).

Thanks for any guidance,
David Aldridge

Reply via email to