Kelly Graus wrote:
Here is the relevant code that uses Xerces to parse the DOM (minus all
the error checking):
OK, there's a little too much code here, and it's not possible to compile
it, so I can't debug it. If you can reduce this to a minimal amount of
code necessary to reproduce the problem, that's usually best.
XERCES_CPP_NAMESPACE::MemBufInputSource* inputSource = new
XERCES_CPP_NAMESPACE::MemBufInputSource( (const XMLByte*)data,
dataLength, cDOMUtilities::convertString( systemID ), false );
I'm not so sure you want to create InputSource instances on the heap.
They are quite small, and can live nicely on the stack.
XERCES_CPP_NAMESPACE::XercesDOMParser* parser = new
XERCES_CPP_NAMESPACE::XercesDOMParser();
parser->setValidationScheme(
XERCES_CPP_NAMESPACE::XercesDOMParser::Val_Auto );
parser->setDoNamespaces( false );
parser->setDoSchema( false );
parser->setCreateEntityReferenceNodes( false );
parser->setCreateCommentNodes( false );
parser->parse( *inputSource );
return new cDOMDocument( parser->adoptDocument() ); //This is our
wrapper class.
And the transform code:
domDocument->normalize(); //This is the Xerces DOMDocument.
XALAN_CPP_NAMESPACE::XalanTransformer transformer;
transformer.setEntityResolver( entityResolver ); //Our custom entity
resolver.
//Set any parameters.
if( mParameterMap != NULL )
{
for( tltCore::cIterator<const tltCore::cMap<tltCore::cString*,
tltCore::cString*>::cEntry*>* iterator =
mParameterMap->getEntries()->createIterator();
iterator->isCurrentElementValid(); iterator->increment() )
{
transformer.setStylesheetParam(
*iterator->getCurrentElement()->getKey(),
*iterator->getCurrentElement()->getValue() );
}
}
XALAN_CPP_NAMESPACE::XSLTInputSource* inputSource = new
XALAN_CPP_NAMESPACE::XSLTInputSource( mStringStream );
Ditto for XSLTInputSource instances -- They are only slightly larger than
instances of InputSource.
//Compile the stylesheet for possible later use.
const XALAN_CPP_NAMESPACE::XalanCompiledStylesheet* compiledStylesheet;
transformer.compileStylesheet( *inputSource, compiledStylesheet );
It looks like you didn't set the system ID on this XSLTInputSource
instance, so there will be no base URI when any xsl:include and xsl:import
instructions are processed. Isn't this the real problem, not the use of a
Xerces DOM as the input?
//Try to get the DOCTYPE.
const XALAN_CPP_NAMESPACE::StylesheetRoot* stylesheetRoot =
compiledStylesheet->getStylesheetRoot();
tltCore::cString doctypeFormat = getDoctypeFormat( stylesheetRoot );
tltCore::cString doctypePublic = getDoctypePublic( stylesheetRoot );
tltCore::cString doctypeSystem = getDoctypeSystem( stylesheetRoot );
//Create the input classes to use the Xerces DOM.
XALAN_CPP_NAMESPACE::XercesDOMSupport xercesDOMSupport;
XALAN_CPP_NAMESPACE::XercesParserLiaison xercesParserLiason;
//NOTE: Tried several different things here for the system id, including
hardcoding the correct path to the XML file.
const XALAN_CPP_NAMESPACE::XercesDOMWrapperParsedSource parsedSource(
domDocument, xercesParserLiason,
xercesDOMSupport, XALAN_CPP_NAMESPACE::XalanDOMString(
domDocument->getDocumentURI() ) );
Technically, this isn't a system ID -- It's the URI for the document.
Since an EntityResolver is only called during parsing, and you've already
parsed the input document, this URI is not going to be very helpful. In
addition, the URI for the input document does not affect the URI for
stylesheet.
//Create the Xerces DOM output.
XERCES_CPP_NAMESPACE::DOMImplementation* domImplementation =
XERCES_CPP_NAMESPACE::DOMImplementation::getImplementation();
XERCES_CPP_NAMESPACE::DOMDocument* outputDOMDocument;
if( !doctypeFormat.equals( "" ) && ( !doctypePublic.equals( "" ) ||
!doctypeSystem.equals( "" ) ) )
{
XERCES_CPP_NAMESPACE::DOMDocumentType* documentType =
domImplementation->createDocumentType(
cDOMUtilities::convertString( doctypeFormat ),
cDOMUtilities::convertString( doctypePublic ),
cDOMUtilities::convertString( doctypeSystem ) );
outputDOMDocument = domImplementation->createDocument( NULL,
NULL, documentType );
}
else
{
outputDOMDocument = domImplementation->createDocument();
}
//Format the output from Xalan to Xerces.
XALAN_CPP_NAMESPACE::FormatterToXercesDOM xercesFormatter(
outputDOMDocument, NULL );
transformer.transform( parsedSource, compiledStylesheet, xercesFormatter );
return new cDOMDocument( outputDOMDocument );
After that I use a Xerces DOMWriter to output the document to an HTML
file. If I comment out the XercesDOMWrapperParsedSource stuff, and pass
in the file name to the transformer, everything works as it should.
I'm not sure why you're transforming to the Xerces-C DOM only to use a
DOMWriter to generate markup. Unless you need a DOM instance for another
purpose, or you're modifying the DOM after the transformation, but before
serialization, generating markup directly is much more efficient.
Dave