DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG 
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://nagoya.apache.org/bugzilla/show_bug.cgi?id=26374>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND 
INSERTED IN THE BUG DATABASE.

http://nagoya.apache.org/bugzilla/show_bug.cgi?id=26374

Transformation ignores xsl:output doctype declaration when transforming to DOM tree

           Summary: Transformation ignores xsl:output doctype declaration
                    when transforming to DOM tree
           Product: XalanC
           Version: 1.5
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: Normal
          Priority: Other
         Component: XalanC
        AssignedTo: [EMAIL PROTECTED]
        ReportedBy: [EMAIL PROTECTED]


When using a FormatterToDOM or FormatterToXercesDOM then the result doesn't 
have a doctype node after transformation even if the doctype-system attribute 
on the xsl:output element is specified.
When using other formatters (FormatterToXML for example) then the doctype node 
is generated.

I have fixed it in our version (Xalan 1.5) like this:

In FormatterListener.hpp I added a new method:

  virtual void documentType(
    const XMLCh* const systemID, 
    const XMLCh* const publicID);

And implemented it in FormatterListener.cpp as an empty method:

  void FormatterListener::documentType(
        const XMLCh* const /* systemID */, 
        const XMLCh* const /* publicID */)
  {
    // Do nothing
  }

I then added code in StylesheetRoot.cpp that calls the new method:

  FormatterListener* StylesheetRoot::setupFormatterListener(
        XSLTResultTarget& outputTarget,
        StylesheetExecutionContext& executionContext) const
  {
        FormatterListener* flistener = outputTarget.getFormatterListener();

        if (flistener != 0)
        {
                // Do encoding stuff here...

/* NEW CODE START */

                // Do documenttype stuff
                if (m_doctypeSystem.empty() == false)
                        flistener->documentType(m_doctypeSystem.c_str(), 
m_doctypePublic.c_str());

/* NEW CODE END */
        }
        else if(0 != outputTarget.getCharacterStream() ||
                        0 != outputTarget.getByteStream() ||
                        0 != length(outputTarget.getFileName()))
        {

Then I added the method to FormatterToDOM.cpp and FormatterToXercesDOM.cpp and 
two extra members:

        virtual void
        documentType(
          const XMLCh* const systemID, 
          const XMLCh* const publicID);

        XalanDOMString m_systemID;
        XalanDOMString m_publicID;

Then I implemented the new method like this:

  void FormatterToDOM::documentType(
        const XMLCh* const systemID, 
        const XMLCh* const publicID)
  {
        assign(m_systemID, systemID);
        assign(m_publicID, publicID);
  }

...and...

  void FormatterToXercesDOM::documentType(
        const XMLCh* const systemID, 
        const XMLCh* const publicID)
  {
        assign(m_systemID, systemID);
        assign(m_publicID, publicID);
  }

And finally I changed the following code in FormatterToDOM and 
FormatterToXercesDOM:

void
FormatterToDOM::append(XalanNode*       newNode)
{
        assert(newNode != 0);

        if(0 != m_currentElem)
        {
                m_currentElem->appendChild(newNode);
        }
        else if(0 != m_docFrag)
        {
                m_docFrag->appendChild(newNode);
        }
        else
        {

/* NEW CODE START */

                if (m_doc->getDocumentElement() == 0
                 && newNode->getNodeType() == XalanNode::ELEMENT_NODE
                 && m_systemID.empty() == false)
                {
                        XalanDocumentType* poOldDocType = m_doc->getDoctype();
                        XalanDocumentType* poNewDocType = m_doc-
>getImplementation()->createDocumentType(newNode->getNodeName(), m_publicID, 
m_systemID);
                        if (poOldDocType)
                                m_doc->replaceChild
(reinterpret_cast<XalanNode*>(poNewDocType), reinterpret_cast<XalanNode*>
(poOldDocType));
                        else
                                m_doc->appendChild(reinterpret_cast<XalanNode*>
(poNewDocType));
                        m_systemID.clear();
                        m_publicID.clear();
                }

/* NEW CODE END */

                m_doc->appendChild(newNode);
        }
}

... and ...

void
FormatterToXercesDOM::append(DOMNodeType*       newNode)
{
        assert(newNode != 0);

        if(0 != m_currentElem)
        {
                m_currentElem->appendChild(newNode);
        }
        else if(0 != m_docFrag)
        {
                m_docFrag->appendChild(newNode);
        }
        else
        {

/* NEW CODE START */

                if (m_doc->getDocumentElement() == 0 
                 && newNode->getNodeType() == DOMNodeType::ELEMENT_NODE
                 && m_systemID.empty() == false)
                {
                        DOMDocumentType* poOldDocType = m_doc->getDoctype();
                        DOMDocumentType* poNewDocType = m_doc-
>getImplementation()->createDocumentType(newNode->getNodeName(), 
m_publicID.c_str(), m_systemID.c_str());
                        if (poOldDocType)
                                m_doc->replaceChild(reinterpret_cast<DOMNode*>
(poNewDocType), reinterpret_cast<DOMNode*>(poOldDocType));
                        else
                                m_doc->appendChild(reinterpret_cast<DOMNode*>
(poNewDocType));
                        m_systemID.clear();
                        m_publicID.clear();
                }

/* NEW CODE END */

                m_doc->appendChild(newNode);
        }
}

The solution works for me and if it is an ok solution please use it. If not? 
Throw it away and solve the bug anyway you like.

/ Erik Rydgren

Reply via email to