You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@xalan.apache.org by bu...@apache.org on 2004/01/23 13:24:20 UTC

DO NOT REPLY [Bug 26374] New: - Transformation ignores xsl:output doctype declaration when transforming to DOM tree

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: xalan-dev@xml.apache.org
        ReportedBy: erik.rydgren@mandarinen.se


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