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

Reply via email to