Back to index

lightning-sunbird  0.9+nobinonly
txMozillaTextOutput.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is TransforMiiX XSLT processor code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 2001
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Peter Van der Beken <peterv@propagandism.org>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either the GNU General Public License Version 2 or later (the "GPL"), or
00027  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "txMozillaTextOutput.h"
00040 #include "nsContentCID.h"
00041 #include "nsIContent.h"
00042 #include "nsIDocument.h"
00043 #include "nsIDOMDocument.h"
00044 #include "nsIDOMDocumentFragment.h"
00045 #include "nsIDOMElement.h"
00046 #include "nsIDOMHTMLElement.h"
00047 #include "nsIDOMText.h"
00048 #include "nsIDocumentTransformer.h"
00049 #include "nsNetUtil.h"
00050 #include "nsIDOMNSDocument.h"
00051 #include "nsIParser.h"
00052 #include "nsICharsetAlias.h"
00053 #include "nsIPrincipal.h"
00054 
00055 static NS_DEFINE_CID(kXMLDocumentCID, NS_XMLDOCUMENT_CID);
00056 
00057 txMozillaTextOutput::txMozillaTextOutput(nsIDOMDocument* aSourceDocument,
00058                                          nsIDOMDocument* aResultDocument,
00059                                          nsITransformObserver* aObserver)
00060 {
00061     mObserver = do_GetWeakReference(aObserver);
00062     createResultDocument(aSourceDocument, aResultDocument);
00063 }
00064 
00065 txMozillaTextOutput::txMozillaTextOutput(nsIDOMDocumentFragment* aDest)
00066 {
00067     nsCOMPtr<nsIDOMDocument> doc;
00068     aDest->GetOwnerDocument(getter_AddRefs(doc));
00069     NS_ASSERTION(doc, "unable to get ownerdocument");
00070     nsCOMPtr<nsIDOMText> textNode;
00071     nsresult rv = doc->CreateTextNode(EmptyString(),
00072                                       getter_AddRefs(textNode));
00073     if (NS_FAILED(rv)) {
00074         return;
00075     }
00076     nsCOMPtr<nsIDOMNode> dummy;
00077     rv = aDest->AppendChild(textNode, getter_AddRefs(dummy));
00078     if (NS_FAILED(rv)) {
00079         return;
00080     }
00081 
00082     mTextNode = textNode;
00083     return;
00084 }
00085 
00086 txMozillaTextOutput::~txMozillaTextOutput()
00087 {
00088 }
00089 
00090 void txMozillaTextOutput::attribute(const nsAString& aName,
00091                                     const PRInt32 aNsID,
00092                                     const nsAString& aValue)
00093 {
00094 }
00095 
00096 void txMozillaTextOutput::characters(const nsAString& aData, PRBool aDOE)
00097 {
00098     if (mTextNode)
00099         mTextNode->AppendData(aData);
00100 }
00101 
00102 void txMozillaTextOutput::comment(const nsAString& aData)
00103 {
00104 }
00105 
00106 void txMozillaTextOutput::endDocument(nsresult aResult)
00107 {
00108     if (NS_SUCCEEDED(aResult)) {
00109         nsCOMPtr<nsITransformObserver> observer = do_QueryReferent(mObserver);
00110         if (observer) {
00111             observer->OnTransformDone(aResult, mDocument);
00112         }
00113     }
00114 }
00115 
00116 void txMozillaTextOutput::endElement(const nsAString& aName,
00117                                      const PRInt32 aNsID)
00118 {
00119 }
00120 
00121 void txMozillaTextOutput::processingInstruction(const nsAString& aTarget,
00122                                                 const nsAString& aData)
00123 {
00124 }
00125 
00126 void txMozillaTextOutput::startDocument()
00127 {
00128 }
00129 
00130 void txMozillaTextOutput::createResultDocument(nsIDOMDocument* aSourceDocument,
00131                                                nsIDOMDocument* aResultDocument)
00132 {
00133     nsresult rv = NS_OK;
00134     
00135     /*
00136      * Create an XHTML document to hold the text.
00137      *
00138      * <html>
00139      *   <head />
00140      *   <body>
00141      *     <pre> * The text comes here * </pre>
00142      *   <body>
00143      * </html>
00144      *
00145      * Except if we are transforming into a non-displayed document we create
00146      * the following DOM
00147      *
00148      * <transformiix:result> * The text comes here * </transformiix:result>
00149      */
00150      
00151     nsCOMPtr<nsIDocument> doc;
00152     if (!aResultDocument) {
00153         // Create the document
00154         doc = do_CreateInstance(kXMLDocumentCID, &rv);
00155         NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create document");
00156         nsCOMPtr<nsIDocument_MOZILLA_1_8_BRANCH3> source =
00157           do_QueryInterface(aSourceDocument);
00158         if (!source) {
00159           return;
00160         }
00161         PRBool hasHadScriptObject = PR_FALSE;
00162         nsIScriptGlobalObject* sgo =
00163           source->GetScriptHandlingObject(hasHadScriptObject);
00164         if (!sgo && hasHadScriptObject) {
00165           return;
00166         }
00167         nsCOMPtr<nsIDocument_MOZILLA_1_8_BRANCH3> doc18 =
00168           do_QueryInterface(doc);
00169         if (!doc18) {
00170           return;
00171         }
00172         doc18->SetScriptHandlingObject(sgo);
00173         mDocument = do_QueryInterface(doc);
00174     }
00175     else {
00176         mDocument = aResultDocument;
00177         doc = do_QueryInterface(aResultDocument);
00178         NS_ASSERTION(doc, "Couldn't QI to nsIDocument");
00179     }
00180 
00181     if (!doc) {
00182         return;
00183     }
00184 
00185     NS_ASSERTION(mDocument, "Need document");
00186 
00187     nsCOMPtr<nsIDOMNSDocument> nsDoc = do_QueryInterface(mDocument);
00188     if (nsDoc) {
00189         nsDoc->SetTitle(EmptyString());
00190     }
00191 
00192     // Reset and set up document
00193     nsCOMPtr<nsIDocument> sourceDoc = do_QueryInterface(aSourceDocument);
00194     nsIPrincipal* sourcePrincipal = sourceDoc->GetPrincipal();
00195     if (!sourcePrincipal) {
00196         return;
00197     }
00198 
00199     nsCOMPtr<nsILoadGroup> loadGroup = sourceDoc->GetDocumentLoadGroup();
00200     nsCOMPtr<nsIChannel> channel = sourceDoc->GetChannel();
00201     if (!channel) {
00202         // Need to synthesize one
00203         if (NS_FAILED(NS_NewChannel(getter_AddRefs(channel),
00204                                     sourceDoc->GetDocumentURI(),
00205                                     nsnull,
00206                                     loadGroup))) {
00207             return;
00208         }
00209         channel->SetOwner(sourcePrincipal);
00210     }
00211     // Copy the channel and loadgroup from the source document.
00212     doc->Reset(channel, loadGroup);
00213     doc->SetPrincipal(sourcePrincipal);
00214     doc->SetBaseURI(sourceDoc->GetBaseURI());
00215 
00216     // Set the charset
00217     if (!mOutputFormat.mEncoding.IsEmpty()) {
00218         NS_LossyConvertUTF16toASCII charset(mOutputFormat.mEncoding);
00219         nsCAutoString canonicalCharset;
00220         nsCOMPtr<nsICharsetAlias> calias =
00221             do_GetService("@mozilla.org/intl/charsetalias;1");
00222 
00223         if (calias &&
00224             NS_SUCCEEDED(calias->GetPreferred(charset, canonicalCharset))) {
00225             doc->SetDocumentCharacterSet(canonicalCharset);
00226             doc->SetDocumentCharacterSetSource(kCharsetFromOtherComponent);
00227         }
00228     }
00229     else {
00230         doc->SetDocumentCharacterSet(sourceDoc->GetDocumentCharacterSet());
00231         doc->SetDocumentCharacterSetSource(
00232             sourceDoc->GetDocumentCharacterSetSource());
00233     }
00234 
00235     // Notify the contentsink that the document is created
00236     nsCOMPtr<nsITransformObserver> observer = do_QueryReferent(mObserver);
00237     if (observer) {
00238         observer->OnDocumentCreated(mDocument);
00239     }
00240 
00241     // Create the content
00242 
00243     // When transforming into a non-displayed document (i.e. when there is no
00244     // observer) we only create a transformiix:result root element.
00245     // Don't do this when called through nsIXSLTProcessorObsolete (i.e. when
00246     // aResultDocument is set) for compability reasons
00247     nsCOMPtr<nsIDOMNode> textContainer;
00248     if (!aResultDocument && !observer) {
00249         nsCOMPtr<nsIDOMElement> docElement;
00250         mDocument->CreateElementNS(NS_LITERAL_STRING(kTXNameSpaceURI),
00251                                    NS_LITERAL_STRING(kTXWrapper),
00252                                    getter_AddRefs(docElement));
00253         NS_ASSERTION(docElement, "Failed to create wrapper element");
00254         if (!docElement) {
00255             return;
00256         }
00257 
00258         rv = mDocument->AppendChild(docElement, getter_AddRefs(textContainer));
00259         NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to append the wrapper element");
00260         if (NS_FAILED(rv)) {
00261             return;
00262         }
00263     }
00264     else {
00265         nsCOMPtr<nsIDOMElement> element, docElement;
00266         nsCOMPtr<nsIDOMNode> parent, pre;
00267 
00268         NS_NAMED_LITERAL_STRING(XHTML_NSURI, "http://www.w3.org/1999/xhtml");
00269 
00270         mDocument->CreateElementNS(XHTML_NSURI,
00271                                    NS_LITERAL_STRING("html"),
00272                                    getter_AddRefs(docElement));
00273         nsCOMPtr<nsIContent> rootContent = do_QueryInterface(docElement);
00274         NS_ASSERTION(rootContent, "Need root element");
00275         if (!rootContent) {
00276             return;
00277         }
00278 
00279         // XXXbz what to do on failure here?
00280         rv = doc->SetRootContent(rootContent);
00281         if (NS_FAILED(rv)) {
00282             NS_ERROR("Failed to set root content");
00283             return;
00284         }
00285             
00286 
00287         mDocument->CreateElementNS(XHTML_NSURI,
00288                                    NS_LITERAL_STRING("head"),
00289                                    getter_AddRefs(element));
00290         NS_ASSERTION(element, "Failed to create head element");
00291         if (!element) {
00292             return;
00293         }
00294 
00295         rv = docElement->AppendChild(element, getter_AddRefs(parent));
00296         NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to append the head element");
00297         if (NS_FAILED(rv)) {
00298             return;
00299         }
00300 
00301         mDocument->CreateElementNS(XHTML_NSURI,
00302                                    NS_LITERAL_STRING("body"),
00303                                    getter_AddRefs(element));
00304         NS_ASSERTION(element, "Failed to create body element");
00305         if (!element) {
00306             return;
00307         }
00308 
00309         rv = docElement->AppendChild(element, getter_AddRefs(parent));
00310         NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to append the body element");
00311         if (NS_FAILED(rv)) {
00312             return;
00313         }
00314 
00315         mDocument->CreateElementNS(XHTML_NSURI,
00316                                    NS_LITERAL_STRING("pre"),
00317                                    getter_AddRefs(element));
00318         NS_ASSERTION(element, "Failed to create pre element");
00319         if (!element) {
00320             return;
00321         }
00322 
00323         rv = parent->AppendChild(element, getter_AddRefs(pre));
00324         NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to append the pre element");
00325         if (NS_FAILED(rv)) {
00326             return;
00327         }
00328 
00329         nsCOMPtr<nsIDOMHTMLElement> htmlElement = do_QueryInterface(pre);
00330         htmlElement->SetId(NS_LITERAL_STRING("transformiixResult"));
00331         NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to append the id");
00332         
00333         textContainer = pre;
00334     }
00335 
00336     nsCOMPtr<nsIDOMText> textNode;
00337     mDocument->CreateTextNode(EmptyString(),
00338                               getter_AddRefs(textNode));
00339     NS_ASSERTION(textNode, "Failed to create the text node");
00340     if (!textNode) {
00341         return;
00342     }
00343 
00344     nsCOMPtr<nsIDOMNode> dummy;
00345     rv = textContainer->AppendChild(textNode, getter_AddRefs(dummy));
00346     NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to append the text node");
00347     if (NS_FAILED(rv)) {
00348         return;
00349     }
00350 
00351     mTextNode = textNode;
00352 }
00353 
00354 void txMozillaTextOutput::startElement(const nsAString& aName,
00355                                        const PRInt32 aNsID)
00356 {
00357 }
00358 
00359 void txMozillaTextOutput::getOutputDocument(nsIDOMDocument** aDocument)
00360 {
00361     *aDocument = mDocument;
00362     NS_IF_ADDREF(*aDocument);
00363 }