Landing XSLT branch. Tracking bug is 155578, fixes bugs 46633, 54659, 73492, 70369, 85408, 90157, 130161, 109918, 150916 and 170097

* New scriptable interfaces to XSLT
* Make HTML-output create real html
* cleanup the XSLTProcessor class

Patch by sicking, pike and peterv

r=sicking/pike, sr=peterv, a=asa
This commit is contained in:
sicking%bigfoot.com 2005-11-02 07:38:42 +00:00
Родитель 9315ec4bc1
Коммит 8e54224bce
28 изменённых файлов: 2809 добавлений и 566 удалений

Просмотреть файл

@ -21,7 +21,7 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk include $(DEPTH)/config/autoconf.mk
DIRS = document DIRS = public document
include $(topsrcdir)/config/config.mk include $(topsrcdir)/config/config.mk

Просмотреть файл

@ -0,0 +1,60 @@
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# Portions created by the Initial Developer are Copyright (C) 2002
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Peter Van der Beken <peterv@netscape.com> (original author)
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = content
XPIDL_MODULE = content_xslt
EXPORTS = \
nsIDocumentTransformer.h \
nsITransformMediator.h \
$(NULL)
XPIDLSRCS = \
nsIXSLTException.idl \
nsIXSLTProcessor.idl \
nsIXSLTProcessorObsolete.idl \
$(NULL)
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -0,0 +1,78 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Jonas Sicking <sicking@bigfoot.com> (Original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsIDocumentTransformer_h__
#define nsIDocumentTransformer_h__
#include "nsISupports.h"
class nsIDOMDocument;
class nsIDOMNode;
#define NS_ITRANSFORMOBSERVER_IID \
{0xcce88481, 0x6eb3, 0x11d6, \
{ 0xa7, 0xf2, 0x8d, 0x82, 0xcd, 0x2a, 0xf3, 0x7c }}
class nsITransformObserver : public nsISupports
{
public:
NS_DEFINE_STATIC_IID_ACCESSOR(NS_ITRANSFORMOBSERVER_IID)
NS_IMETHOD OnDocumentCreated(nsIDOMDocument *aResultDocument) = 0;
NS_IMETHOD OnTransformDone(nsresult aResult, nsIDOMDocument *aResultDocument) = 0;
};
#define NS_IDOCUMENTTRANSFORMER_IID \
{0x43e5a6c6, 0xa53c, 0x4f97, \
{ 0x91, 0x79, 0x47, 0xf2, 0x46, 0xec, 0xd9, 0xd6 }}
class nsIDocumentTransformer : public nsISupports
{
public:
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IDOCUMENTTRANSFORMER_IID)
NS_IMETHOD TransformDocument(nsIDOMNode *aSourceDOM,
nsIDOMNode *aStyleDOM,
nsITransformObserver *aObserver,
nsIDOMDocument **_retval) = 0;
};
#endif //nsIDocumentTransformer_h__

Просмотреть файл

@ -0,0 +1,53 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is TransforMiiX XSLT Processor.
*
* The Initial Developer of the Original Code is
* Axel Hecht.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Axel Hecht, <axel@pike.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsIException.idl"
#include "domstubs.idl"
[scriptable, uuid(e06dfaea-92d5-47f7-a800-c5f5404d8771)]
interface nsIXSLTException : nsIException {
/**
* The node in the stylesheet that triggered the exception.
*/
readonly attribute nsIDOMNode styleNode;
/**
* The context node, may be null
*/
readonly attribute nsIDOMNode sourceNode;
};

Просмотреть файл

@ -0,0 +1,131 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is TransforMiiX XSLT Processor.
*
* The Initial Developer of the Original Code is
* Axel Hecht.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Axel Hecht, <axel@pike.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
#include "domstubs.idl"
interface nsIVariant;
[scriptable, uuid(4a91aeb3-4100-43ee-a21e-9866268757c5)]
interface nsIXSLTProcessor : nsISupports
{
/**
* Import the stylesheet into this XSLTProcessor for transformations.
*
* Note: Changing the DOM of the stylesheet document after it has been
* imported does not affect the processor. It will apply the
* stylesheet as it looked at the time of the call to
* importStylesheet
*
* @param style The root-node of a XSLT stylesheet. This can be either
* a document node or an element node. If a document node
* then the document can contain either a XSLT stylesheet
* or a LRE stylesheet.
* If the argument is an element node it must be the
* xsl:stylesheet (or xsl:transform) element of an XSLT
* stylesheet.
*
* @exception nsIXSLTException
*/
void importStylesheet(in nsIDOMNode style);
/**
* Transforms the node source applying the stylesheet given by
* the importStylesheet() function. The owner document of the output node
* owns the returned document fragment.
*
* @param source The node to be transformed
* @param output The owner document of this node is used to generate
* the output
* @return DocumentFragment The result of the transformation
*
* @exception nsIXSLTException
*/
nsIDOMDocumentFragment transformToFragment(in nsIDOMNode source,
in nsIDOMDocument output);
/**
* Transforms the node source applying the stylesheet given by the
* importStylesheet() function.
*
* @param source The node to be transformed
* @param output The owner document of this node is used to generate
* the output
* @return DocumentFragment The result of the transformation
*
* @exception nsIXSLTException
*/
nsIDOMDocument transformToDocument(in nsIDOMNode source);
/**
* Sets a parameter to be used in the following calls to transformNode.
*
* @param namespaceURI The namespaceURI of the XSLT parameter
* @param localName The local name of the XSLT parameter
* @param value The new value of the XSLT parameter
*
* @exception NS_ERROR_ILLEGAL_VALUE The datatype of value is
* not supported
*/
void setParameter(in DOMString namespaceURI,
in DOMString localName,
in nsIVariant value);
/**
* Gets a parameter, if set and return null otherwise.
*
* @param namespaceURI The namespaceURI of the XSLT parameter
* @param localName The local name of the XSLT parameter
* @return nsIVariant The value of the XSLT parameter
*/
nsIVariant getParameter(in DOMString namespaceURI,
in DOMString localName);
/**
* Removes a parameter, if set.
*
* @param namespaceURI The namespaceURI of the XSLT parameter
* @param localName The local name of the XSLT parameter
*/
void removeParameter(in DOMString namespaceURI,
in DOMString localName);
/**
* Removes all set parameters from this nsIXSLTProcessor
*/
void clearParameters();
};

Просмотреть файл

@ -0,0 +1,57 @@
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Nisheeth Ranjan <nisheeth@netscape.com> (original author)
* Peter Van der Beken <peterv@netscape.com>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
interface nsIDOMNode;
interface nsIDOMDocument;
/**
* DEPRECATED! Don't use this interface! Use nsIXSLTProcessor instead!!
*/
[scriptable, uuid(3fbff728-2d20-11d3-aef3-00108300ff91)]
interface nsIXSLTProcessorObsolete : nsISupports
{
void transformDocument(in nsIDOMNode aSourceDOM,
in nsIDOMNode aStyleDOM,
in nsIDOMDocument aOutputDOC,
in nsISupports aObserver);
};

Просмотреть файл

@ -26,7 +26,14 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk include $(DEPTH)/config/autoconf.mk
PROGRAM = ../transformiix$(BIN_SUFFIX) LIBRARY_NAME = tx
FORCE_STATIC_LIB = 1
SIMPLE_PROGRAMS = transformiix$(BIN_SUFFIX)
ifdef MARK_INC
SIMPLE_PROGRAMS += txXSLTMarkDriver$(BIN_SUFFIX)
endif
EXTRA_DEPS = $(LIBRARY)
REQUIRES = expat \ REQUIRES = expat \
$(NULL) $(NULL)
@ -109,6 +116,7 @@ OBJS =../base/ArrayList.$(OBJ_SUFFIX) \
../xslt/txXSLTPatterns.$(OBJ_SUFFIX) \ ../xslt/txXSLTPatterns.$(OBJ_SUFFIX) \
../xslt/txPatternParser.$(OBJ_SUFFIX) \ ../xslt/txPatternParser.$(OBJ_SUFFIX) \
../xslt/XSLTProcessor.$(OBJ_SUFFIX) \ ../xslt/XSLTProcessor.$(OBJ_SUFFIX) \
../xslt/txStandaloneXSLTProcessor.$(OBJ_SUFFIX) \
../xslt/functions/CurrentFunctionCall.$(OBJ_SUFFIX) \ ../xslt/functions/CurrentFunctionCall.$(OBJ_SUFFIX) \
../xslt/functions/DocumentFunctionCall.$(OBJ_SUFFIX) \ ../xslt/functions/DocumentFunctionCall.$(OBJ_SUFFIX) \
../xslt/functions/ElementAvailableFnCall.$(OBJ_SUFFIX) \ ../xslt/functions/ElementAvailableFnCall.$(OBJ_SUFFIX) \
@ -118,11 +126,13 @@ OBJS =../base/ArrayList.$(OBJ_SUFFIX) \
../xslt/functions/txFormatNumberFunctionCall.$(OBJ_SUFFIX) \ ../xslt/functions/txFormatNumberFunctionCall.$(OBJ_SUFFIX) \
../xslt/functions/txKeyFunctionCall.$(OBJ_SUFFIX) \ ../xslt/functions/txKeyFunctionCall.$(OBJ_SUFFIX) \
../xslt/util/txNodeSorter.$(OBJ_SUFFIX) \ ../xslt/util/txNodeSorter.$(OBJ_SUFFIX) \
../xslt/util/txXPathResultComparator.$(OBJ_SUFFIX) \ ../xslt/util/txXPathResultComparator.$(OBJ_SUFFIX)
transformiix.$(OBJ_SUFFIX)
CPP_PROG_LINK = 1 CPP_PROG_LINK = 1
EXTRA_LIBS = \ EXTRA_LIBS = \
$(LIB_PREFIX)tx.$(LIB_SUFFIX) \
$(NULL)
SHARED_LIBRARY_LIBS = \
$(DIST)/lib/$(LIB_PREFIX)expat_s.$(LIB_SUFFIX) \ $(DIST)/lib/$(LIB_PREFIX)expat_s.$(LIB_SUFFIX) \
$(DIST)/lib/$(LIB_PREFIX)xmltok_s.$(LIB_SUFFIX) \ $(DIST)/lib/$(LIB_PREFIX)xmltok_s.$(LIB_SUFFIX) \
$(NULL) $(NULL)
@ -133,4 +143,4 @@ INCLUDES += -I$(srcdir)/../xslt -I$(srcdir)/../base -I$(srcdir)/../net \
-I$(srcdir)/../xml -I$(srcdir)/../xml/dom \ -I$(srcdir)/../xml -I$(srcdir)/../xml/dom \
-I$(srcdir)/../xml/parser \ -I$(srcdir)/../xml/parser \
-I$(srcdir)/../xpath -I$(srcdir)/../xslt/util \ -I$(srcdir)/../xpath -I$(srcdir)/../xslt/util \
-I$(srcdir)/../xslt/functions -I$(srcdir)/../xslt/functions $(MARK_INC)

Просмотреть файл

@ -29,14 +29,13 @@
* *
* Olivier Gerardin, ogerardin@vo.lu * Olivier Gerardin, ogerardin@vo.lu
* -- redirect non-data output (banner, errors) to stderr * -- redirect non-data output (banner, errors) to stderr
* -- read XML from stdin when -i is omitted
* -- accept '-' to specify stdin/stdout on command line
* *
*/ */
#include "XSLTProcessor.h" #include "txStandaloneXSLTProcessor.h"
#include "CommandLineUtils.h" #include "CommandLineUtils.h"
#include <fstream.h>
//--------------/ //--------------/
//- Prototypes -/ //- Prototypes -/
@ -57,13 +56,8 @@ void printUsage();
**/ **/
int main(int argc, char** argv) { int main(int argc, char** argv) {
if (!txInit()) if (!txXSLTProcessor::txInit())
return 1; return 1;
XSLTProcessor xsltProcessor;
//-- add ErrorObserver
SimpleErrorObserver seo;
xsltProcessor.addErrorObserver(seo);
//-- available flags //-- available flags
StringList flags; StringList flags;
@ -79,8 +73,8 @@ int main(int argc, char** argv) {
if (!options.get(String("q"))) { if (!options.get(String("q"))) {
String copyright("(C) 1999 The MITRE Corporation, Keith Visco, and contributors"); String copyright("(C) 1999 The MITRE Corporation, Keith Visco, and contributors");
cerr << xsltProcessor.getAppName() << " "; cerr << "TransforMiiX ";
cerr << xsltProcessor.getAppVersion() << endl; cerr << "1.2b pre" << endl;
cerr << copyright << endl; cerr << copyright << endl;
//-- print banner line //-- print banner line
PRUint32 fillSize = copyright.length() + 1; PRUint32 fillSize = copyright.length() + 1;
@ -98,63 +92,52 @@ int main(int argc, char** argv) {
String* xsltFilename = (String*)options.get(String("s")); String* xsltFilename = (String*)options.get(String("s"));
String* outFilename = (String*)options.get(String("o")); String* outFilename = (String*)options.get(String("o"));
//-- open XML file
istream* xmlInput = &cin;
if (xmlFilename && ! xmlFilename->isEqual("-")) {
xmlInput = new ifstream(NS_LossyConvertUCS2toASCII(*xmlFilename).get(),
ios::in);
}
//-- handle output stream //-- handle output stream
ostream* resultOutput = &cout; ostream* resultOutput = &cout;
ofstream resultFileStream; ofstream resultFileStream;
if ( outFilename && ! outFilename->isEqual("-")) { if (outFilename && !outFilename->isEqual("-")) {
resultFileStream.open(NS_LossyConvertUCS2toASCII(*outFilename).get(), resultFileStream.open(NS_LossyConvertUCS2toASCII(*outFilename).get(),
ios::out); ios::out);
if ( !resultFileStream ) { if (!resultFileStream) {
cerr << "error opening output file: " << *xmlFilename << endl; cerr << "error opening output file: " << *xmlFilename << endl;
return -1; return -1;
} }
resultOutput = &resultFileStream; resultOutput = &resultFileStream;
} }
SimpleErrorObserver obs;
txStandaloneXSLTProcessor proc;
nsresult rv = NS_OK;
//-- process //-- process
String documentBase; if (!xsltFilename) {
if ( !xsltFilename ) { if (!xmlFilename) {
if (!xmlFilename) { cerr << "you must specify at least a source XML path" << endl;
cerr << "you must specify XSLT file with -s option if XML is read from standard input" << endl; printUsage();
printUsage(); return -1;
return -1; }
} rv = proc.transform(*xmlFilename, *resultOutput, obs);
xsltProcessor.process(*xmlInput, *xmlFilename, *resultOutput);
} }
else { else {
//-- open XSLT file //-- open XSLT file
ifstream xsltInput(NS_LossyConvertUCS2toASCII(*xsltFilename).get(), rv = proc.transform(*xmlFilename, *xsltFilename, *resultOutput, obs);
ios::in);
xsltProcessor.process(*xmlInput, *xmlFilename, xsltInput, *xsltFilename, *resultOutput);
} }
resultFileStream.close(); resultFileStream.close();
if (xmlInput != &cin) txXSLTProcessor::txShutdown();
delete xmlInput; return NS_SUCCEEDED(rv);
txShutdown();
return 0;
} //-- main } //-- main
void printHelp() { void printHelp() {
cerr << "transfrmx [-h] [-i xml-file] [-s xslt-file] [-o output-file]" << endl << endl; cerr << "transfrmx [-h] [-i xml-file] [-s xslt-file] [-o output-file]" << endl << endl;
cerr << "Options:"; cerr << "Options:";
cerr << endl << endl; cerr << endl << endl;
cerr << "\t-i specify XML file to process (default: read from stdin)" << endl; cerr << "\t-i specify XML file to process" << endl;
cerr << "\t-s specify XSLT file to use for processing (default: use stylesheet" << endl cerr << "\t-s specify XSLT file to use for processing (default: use stylesheet" << endl
<< "\t\tspecified in XML file)" << endl; << "\t\tspecified in XML file)" << endl;
cerr << "\t-o specify output file (default: write to stdout)" << endl; cerr << "\t-o specify output file (default: write to stdout)" << endl;
cerr << "\t-h this help screen" << endl; cerr << "\t-h this help screen" << endl;
cerr << endl; cerr << endl;
cerr << "You may use '-' in place of xml-file or output-file to explicitly specify" << endl; cerr << "You may use '-' in place of the output-file to explicitly specify" << endl;
cerr << "respectively the standard input and standard output." << endl; cerr << "standard output." << endl;
cerr << "If the XML is read from stdin, then the -s option is mandatory." << endl;
cerr << endl; cerr << endl;
} }
void printUsage() { void printUsage() {

Просмотреть файл

@ -0,0 +1,119 @@
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Axel Hecht <axel@pike.org> (original author)
*
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/**
* Driver for running XSLTMark on standalone
*
* See http://www.datapower.com/XSLTMark/
*/
#include "txStandaloneXSLTProcessor.h"
#include "xmExternalDriver.hpp"
class txDriverProcessor : public txStandaloneXSLTProcessor,
public xmExternalDriver
{
public:
txDriverProcessor() : mXSL(0), mXML(0), mOut(0)
{
}
int loadStylesheet (char * filename)
{
delete mXSL;
mXSL = parsePath(String(filename), mObserver);
return mXSL ? 0 : 1;
}
int setInputDocument (char * filename)
{
delete mXML;
mXML = parsePath(String(filename), mObserver);
return mXML ? 0 : 1;
}
int openOutput (char * outputFilename)
{
mOut = new ofstream(outputFilename);
return mXML ? 0 : 1;
}
int runTransform ()
{
nsresult rv = transform(mXML, mXSL, *mOut, mObserver);
return NS_FAILED(rv);
}
int closeOutput ()
{
if (mOut)
mOut->close();
delete mOut;
mOut = 0;
return 0;
}
int terminate()
{
delete mXSL;
mXSL = 0;
delete mXML;
mXML = 0;
if (mOut && mOut->is_open())
mOut->close();
delete mOut;
mOut = 0;
return 0;
}
~txDriverProcessor()
{
delete mXSL;
delete mXML;
delete mOut;
}
private:
Document *mXSL, *mXML;
SimpleErrorObserver mObserver;
ofstream* mOut;
};
int main (int argc, char ** argv)
{
txDriverProcessor driver;
if (!txDriverProcessor::txInit())
return 1;
driver.main (argc, argv);
txDriverProcessor::txShutdown();
return 0;
}

Просмотреть файл

@ -154,7 +154,7 @@ nsresult nsXPathEvaluator::ParseContextImpl::resolveNamespacePrefix
} }
if (!mNSMan) { if (!mNSMan) {
mNSMan = do_CreateInstance(kNameSpaceManagerCID); mNSMan = do_GetService(kNameSpaceManagerCID);
if (!mNSMan) { if (!mNSMan) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }

Просмотреть файл

@ -42,6 +42,7 @@ REQUIRES = string \
htmlparser \ htmlparser \
webshell \ webshell \
docshell \ docshell \
layout \
$(NULL) $(NULL)
endif endif
@ -54,16 +55,18 @@ CPPSRCS = Names.cpp \
txXSLTNumberCounters.cpp \ txXSLTNumberCounters.cpp \
txXSLTPatterns.cpp \ txXSLTPatterns.cpp \
txPatternParser.cpp \ txPatternParser.cpp \
txUnknownHandler.cpp \
XSLTProcessor.cpp XSLTProcessor.cpp
ifdef TX_EXE ifdef TX_EXE
CPPSRCS += txHTMLOutput.cpp \ CPPSRCS += txHTMLOutput.cpp \
txStandaloneXSLTProcessor.cpp \
txTextOutput.cpp \ txTextOutput.cpp \
txUnknownHandler.cpp \
txXMLOutput.cpp txXMLOutput.cpp
else else
CPPSRCS += txMozillaTextOutput.cpp \ CPPSRCS += txMozillaTextOutput.cpp \
txMozillaXMLOutput.cpp txMozillaXMLOutput.cpp \
txMozillaXSLTProcessor.cpp
endif endif
include $(topsrcdir)/config/rules.mk include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -41,7 +41,8 @@
#include "txOutputFormat.h" #include "txOutputFormat.h"
#include "XMLUtils.h" #include "XMLUtils.h"
txHTMLOutput::txHTMLOutput() txHTMLOutput::txHTMLOutput(txOutputFormat* aFormat, ostream* aOut)
: txXMLOutput(aFormat, aOut)
{ {
mUseEmptyElementShorthand = MB_FALSE; mUseEmptyElementShorthand = MB_FALSE;

Просмотреть файл

@ -46,7 +46,7 @@
class txHTMLOutput : public txXMLOutput class txHTMLOutput : public txXMLOutput
{ {
public: public:
txHTMLOutput(); txHTMLOutput(txOutputFormat* aFormat, ostream* aOut);
~txHTMLOutput(); ~txHTMLOutput();
/* /*

Просмотреть файл

@ -37,21 +37,58 @@
* ***** END LICENSE BLOCK ***** */ * ***** END LICENSE BLOCK ***** */
#include "txMozillaTextOutput.h" #include "txMozillaTextOutput.h"
#include "nsContentCID.h"
#include "nsIDocument.h" #include "nsIDocument.h"
#include "nsIDOMDocument.h" #include "nsIDOMDocument.h"
#include "nsIDOMElement.h" #include "nsIDOMElement.h"
#include "nsIDOMHTMLElement.h" #include "nsIDOMHTMLElement.h"
#include "nsIDOMText.h" #include "nsIDOMText.h"
#include "nsIDocumentTransformer.h"
#include "TxString.h" #include "TxString.h"
#include "nsNetUtil.h"
#include "nsIDOMNSDocument.h"
txMozillaTextOutput::txMozillaTextOutput() static NS_DEFINE_CID(kXMLDocumentCID, NS_XMLDOCUMENT_CID);
txMozillaTextOutput::txMozillaTextOutput(nsIDOMDocument* aSourceDocument,
nsIDOMDocument* aResultDocument,
nsITransformObserver* aObserver)
{ {
NS_INIT_ISUPPORTS();
mObserver = do_GetWeakReference(aObserver);
createResultDocument(aSourceDocument, aResultDocument);
}
txMozillaTextOutput::txMozillaTextOutput(nsIDOMDocumentFragment* aDest)
{
NS_INIT_ISUPPORTS();
nsCOMPtr<nsIDOMDocument> doc;
aDest->GetOwnerDocument(getter_AddRefs(doc));
NS_ASSERTION(doc, "unable to get ownerdocument");
nsCOMPtr<nsIDOMText> textNode;
nsresult rv = doc->CreateTextNode(NS_LITERAL_STRING(""),
getter_AddRefs(textNode));
if (NS_FAILED(rv)) {
return;
}
nsCOMPtr<nsIDOMNode> dummy;
rv = aDest->AppendChild(textNode, getter_AddRefs(dummy));
if (NS_FAILED(rv)) {
return;
}
mTextNode = textNode;
return;
} }
txMozillaTextOutput::~txMozillaTextOutput() txMozillaTextOutput::~txMozillaTextOutput()
{ {
} }
NS_IMPL_ISUPPORTS1(txMozillaTextOutput, txIOutputXMLEventHandler);
void txMozillaTextOutput::attribute(const String& aName, void txMozillaTextOutput::attribute(const String& aName,
const PRInt32 aNsID, const PRInt32 aNsID,
const String& aValue) const String& aValue)
@ -68,12 +105,12 @@ void txMozillaTextOutput::comment(const String& aData)
{ {
} }
void txMozillaTextOutput::disableStylesheetLoad()
{
}
void txMozillaTextOutput::endDocument() void txMozillaTextOutput::endDocument()
{ {
nsCOMPtr<nsITransformObserver> observer = do_QueryReferent(mObserver);
if (observer) {
observer->OnTransformDone(NS_OK, mDocument);
}
} }
void txMozillaTextOutput::endElement(const String& aName, void txMozillaTextOutput::endElement(const String& aName,
@ -81,35 +118,19 @@ void txMozillaTextOutput::endElement(const String& aName,
{ {
} }
nsresult txMozillaTextOutput::getRootContent(nsIContent** aReturn)
{
NS_ASSERTION(aReturn, "NULL pointer passed to getRootContent");
*aReturn = mRootContent;
NS_IF_ADDREF(*aReturn);
return NS_OK;
}
PRBool txMozillaTextOutput::isDone()
{
return PR_TRUE;
}
void txMozillaTextOutput::processingInstruction(const String& aTarget, void txMozillaTextOutput::processingInstruction(const String& aTarget,
const String& aData) const String& aData)
{ {
} }
void txMozillaTextOutput::removeScriptElement(nsIDOMHTMLScriptElement *aElement) void txMozillaTextOutput::startDocument()
{ {
NS_NOTREACHED("No script elements in text output, so this is weird!");
} }
void txMozillaTextOutput::setOutputDocument(nsIDOMDocument* aDocument) void txMozillaTextOutput::createResultDocument(nsIDOMDocument* aSourceDocument,
nsIDOMDocument* aResultDocument)
{ {
NS_ASSERTION(aDocument, "Document can't be NULL!"); nsresult rv = NS_OK;
if (!aDocument)
return;
/* /*
* Create an XHTML document to hold the text. * Create an XHTML document to hold the text.
@ -120,92 +141,172 @@ void txMozillaTextOutput::setOutputDocument(nsIDOMDocument* aDocument)
* <pre> * The text comes here * </pre> * <pre> * The text comes here * </pre>
* <body> * <body>
* </html> * </html>
*
* Except if we are transforming into a non-displayed document we create
* the following DOM
*
* <transformiix:result> * The text comes here * </transformiix:result>
*/ */
nsCOMPtr<nsIDOMElement> element, docElement; nsCOMPtr<nsIDocument> doc;
nsCOMPtr<nsIDOMNode> parent, pre; if (!aResultDocument) {
// Create the document
doc = do_CreateInstance(kXMLDocumentCID, &rv);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create document");
mDocument = do_QueryInterface(doc);
}
else {
mDocument = aResultDocument;
doc = do_QueryInterface(aResultDocument);
NS_ASSERTION(doc, "Couldn't QI to nsIDocument");
}
if (!doc) {
return;
}
NS_ASSERTION(mDocument, "Need document");
nsCOMPtr<nsIDOMNSDocument> nsDoc = do_QueryInterface(mDocument);
if (nsDoc) {
nsDoc->SetTitle(NS_LITERAL_STRING(""));
}
// Reset and set up document
nsCOMPtr<nsILoadGroup> loadGroup;
nsCOMPtr<nsIChannel> channel;
nsCOMPtr<nsIDocument> sourceDoc = do_QueryInterface(aSourceDocument);
sourceDoc->GetDocumentLoadGroup(getter_AddRefs(loadGroup));
nsCOMPtr<nsIIOService> serv = do_GetService(NS_IOSERVICE_CONTRACTID);
if (serv) {
// Create a temporary channel to get nsIDocument->Reset to
// do the right thing. We want the output document to get
// much of the input document's characteristics.
nsCOMPtr<nsIURI> docURL;
sourceDoc->GetDocumentURL(getter_AddRefs(docURL));
serv->NewChannelFromURI(docURL, getter_AddRefs(channel));
}
doc->Reset(channel, loadGroup);
nsCOMPtr<nsIURI> baseURL;
sourceDoc->GetBaseURL(*getter_AddRefs(baseURL));
doc->SetBaseURL(baseURL);
// XXX We might want to call SetDefaultStylesheets here
// Notify the contentsink that the document is created
nsCOMPtr<nsITransformObserver> observer = do_QueryReferent(mObserver);
if (observer) {
observer->OnDocumentCreated(mDocument);
}
// Create the content
// When transforming into a non-displayed document (i.e. when there is no
// observer) we only create a transformiix:result root element.
// Don't do this when called through nsIXSLTProcessorObsolete (i.e. when
// aResultDocument is set) for compability reasons
nsCOMPtr<nsIDOMNode> textContainer;
if (!aResultDocument && !observer) {
nsCOMPtr<nsIDOMElement> docElement;
mDocument->CreateElementNS(NS_LITERAL_STRING(kTXNameSpaceURI),
NS_LITERAL_STRING(kTXWrapper),
getter_AddRefs(docElement));
NS_ASSERTION(docElement, "Failed to create wrapper element");
if (!docElement) {
return;
}
rv = mDocument->AppendChild(docElement, getter_AddRefs(textContainer));
NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to append the wrapper element");
if (NS_FAILED(rv)) {
return;
}
}
else {
nsCOMPtr<nsIDOMElement> element, docElement;
nsCOMPtr<nsIDOMNode> parent, pre;
NS_NAMED_LITERAL_STRING(XHTML_NSURI, "http://www.w3.org/1999/xhtml");
mDocument->CreateElementNS(XHTML_NSURI,
NS_LITERAL_STRING("html"),
getter_AddRefs(docElement));
nsCOMPtr<nsIContent> rootContent = do_QueryInterface(docElement);
NS_ASSERTION(rootContent, "Need root element");
if (!rootContent) {
return;
}
rv = rootContent->SetDocument(doc, PR_FALSE, PR_TRUE);
NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to set the document");
if (NS_FAILED(rv)) {
return;
}
rv = doc->SetRootContent(rootContent);
NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to set the root content");
if (NS_FAILED(rv)) {
return;
}
mDocument->CreateElementNS(XHTML_NSURI,
NS_LITERAL_STRING("head"),
getter_AddRefs(element));
NS_ASSERTION(element, "Failed to create head element");
if (!element) {
return;
}
rv = docElement->AppendChild(element, getter_AddRefs(parent));
NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to append the head element");
if (NS_FAILED(rv)) {
return;
}
mDocument->CreateElementNS(XHTML_NSURI,
NS_LITERAL_STRING("body"),
getter_AddRefs(element));
NS_ASSERTION(element, "Failed to create body element");
if (!element) {
return;
}
rv = docElement->AppendChild(element, getter_AddRefs(parent));
NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to append the body element");
if (NS_FAILED(rv)) {
return;
}
mDocument->CreateElementNS(XHTML_NSURI,
NS_LITERAL_STRING("pre"),
getter_AddRefs(element));
NS_ASSERTION(element, "Failed to create pre element");
if (!element) {
return;
}
rv = parent->AppendChild(element, getter_AddRefs(pre));
NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to append the pre element");
if (NS_FAILED(rv)) {
return;
}
nsCOMPtr<nsIDOMHTMLElement> htmlElement = do_QueryInterface(pre);
htmlElement->SetId(NS_LITERAL_STRING("transformiixResult"));
NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to append the id");
textContainer = pre;
}
nsCOMPtr<nsIDOMText> textNode; nsCOMPtr<nsIDOMText> textNode;
mDocument->CreateTextNode(NS_LITERAL_STRING(""),
NS_NAMED_LITERAL_STRING(XHTML_NSURI, "http://www.w3.org/1999/xhtml");
aDocument->CreateElementNS(XHTML_NSURI,
NS_LITERAL_STRING("html"),
getter_AddRefs(docElement));
mRootContent = do_QueryInterface(docElement);
NS_ASSERTION(mRootContent, "Need root element");
if (!mRootContent) {
return;
}
nsCOMPtr<nsIDocument> document = do_QueryInterface(aDocument);
NS_ASSERTION(document, "Need document");
nsresult rv = mRootContent->SetDocument(document, PR_FALSE, PR_TRUE);
NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to set the document");
if (NS_FAILED(rv)) {
return;
}
rv = document->SetRootContent(mRootContent);
NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to set the root content");
if (NS_FAILED(rv)) {
return;
}
aDocument->CreateElementNS(XHTML_NSURI,
NS_LITERAL_STRING("head"),
getter_AddRefs(element));
NS_ASSERTION(element, "Failed to create head element");
if (!element) {
return;
}
rv = docElement->AppendChild(element, getter_AddRefs(parent));
NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to append the head element");
if (NS_FAILED(rv)) {
return;
}
aDocument->CreateElementNS(XHTML_NSURI,
NS_LITERAL_STRING("body"),
getter_AddRefs(element));
NS_ASSERTION(element, "Failed to create body element");
if (!mRootContent) {
return;
}
rv = docElement->AppendChild(element, getter_AddRefs(parent));
NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to append the body element");
if (NS_FAILED(rv)) {
return;
}
aDocument->CreateElementNS(XHTML_NSURI,
NS_LITERAL_STRING("pre"),
getter_AddRefs(element));
NS_ASSERTION(element, "Failed to create pre element");
if (!element) {
return;
}
rv = parent->AppendChild(element, getter_AddRefs(pre));
NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to append the pre element");
if (NS_FAILED(rv)) {
return;
}
nsCOMPtr<nsIDOMHTMLElement> htmlElement = do_QueryInterface(pre);
htmlElement->SetId(NS_LITERAL_STRING("transformiixResult"));
NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to append the id");
aDocument->CreateTextNode(NS_LITERAL_STRING(""),
getter_AddRefs(textNode)); getter_AddRefs(textNode));
NS_ASSERTION(textNode, "Failed to create the text node"); NS_ASSERTION(textNode, "Failed to create the text node");
if (!textNode) { if (!textNode) {
return; return;
} }
rv = pre->AppendChild(textNode, getter_AddRefs(parent)); nsCOMPtr<nsIDOMNode> dummy;
rv = textContainer->AppendChild(textNode, getter_AddRefs(dummy));
NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to append the text node"); NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to append the text node");
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
return; return;
@ -214,18 +315,13 @@ void txMozillaTextOutput::setOutputDocument(nsIDOMDocument* aDocument)
mTextNode = textNode; mTextNode = textNode;
} }
void txMozillaTextOutput::setOutputFormat(txOutputFormat* aOutputFormat)
{
mOutputFormat.reset();
mOutputFormat.merge(*aOutputFormat);
mOutputFormat.setFromDefaults();
}
void txMozillaTextOutput::startDocument()
{
}
void txMozillaTextOutput::startElement(const String& aName, void txMozillaTextOutput::startElement(const String& aName,
const PRInt32 aNsID) const PRInt32 aNsID)
{ {
} }
void txMozillaTextOutput::getOutputDocument(nsIDOMDocument** aDocument)
{
*aDocument = mDocument;
NS_IF_ADDREF(*aDocument);
}

Просмотреть файл

@ -43,14 +43,24 @@
#include "nsIContent.h" #include "nsIContent.h"
#include "nsIDOMCharacterData.h" #include "nsIDOMCharacterData.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsWeakPtr.h"
#include "txOutputFormat.h" #include "txOutputFormat.h"
#include "nsIDOMDocument.h"
#include "nsIDOMDocumentFragment.h"
class txMozillaTextOutput : public txMozillaXMLEventHandler class nsITransformObserver;
class txMozillaTextOutput : public txIOutputXMLEventHandler
{ {
public: public:
txMozillaTextOutput(); txMozillaTextOutput(nsIDOMDocument* aSourceDocument,
nsIDOMDocument* aResultDocument,
nsITransformObserver* aObserver);
txMozillaTextOutput(nsIDOMDocumentFragment* aDest);
virtual ~txMozillaTextOutput(); virtual ~txMozillaTextOutput();
NS_DECL_ISUPPORTS
/** /**
* Signals to receive the start of an attribute. * Signals to receive the start of an attribute.
* *
@ -69,6 +79,16 @@ public:
*/ */
void characters(const String& aData); void characters(const String& aData);
/**
* Signals to receive characters that don't need output escaping.
*
* @param aData the characters to receive
*/
void charactersNoOutputEscaping(const String& aData)
{
NS_ASSERTION(0, "Don't call this in module, we don't do d-o-e");
}
/** /**
* Signals to receive data that should be treated as a comment. * Signals to receive data that should be treated as a comment.
* *
@ -91,6 +111,18 @@ public:
void endElement(const String& aName, void endElement(const String& aName,
const PRInt32 aNsID); const PRInt32 aNsID);
/**
* Returns whether the output handler supports
* disable-output-escaping.
*
* @return MB_TRUE if this handler supports
* disable-output-escaping
*/
MBool hasDisableOutputEscaping()
{
return MB_FALSE;
}
/** /**
* Signals to receive a processing instruction. * Signals to receive a processing instruction.
* *
@ -114,48 +146,19 @@ public:
const PRInt32 aNsID); const PRInt32 aNsID);
/** /**
* Sets the output format. * Gets the Mozilla output document
*
* @param aOutputFormat the output format
*/
void setOutputFormat(txOutputFormat* aOutputFormat);
/**
* Disables loading of stylesheets.
*/
void disableStylesheetLoad();
/**
* Returns the root content of the result.
*
* @param aReturn the root content
*/
nsresult getRootContent(nsIContent** aReturn);
/**
* Returns PR_TRUE if the event handler has finished anything
* extra that had to happen after the transform has finished.
*/
PRBool isDone();
/**
* Removes a script element from the array of elements that are
* still loading.
*
* @param aReturn the script element to remove
*/
void removeScriptElement(nsIDOMHTMLScriptElement *aElement);
/**
* Sets the Mozilla output document.
* *
* @param aDocument the Mozilla output document * @param aDocument the Mozilla output document
*/ */
void setOutputDocument(nsIDOMDocument* aDocument); void getOutputDocument(nsIDOMDocument** aDocument);
private: private:
void createResultDocument(nsIDOMDocument* aSourceDocument,
nsIDOMDocument* aResultDocument);
nsCOMPtr<nsIDOMCharacterData> mTextNode; nsCOMPtr<nsIDOMCharacterData> mTextNode;
nsCOMPtr<nsIContent> mRootContent; nsWeakPtr mObserver;
nsCOMPtr<nsIDOMDocument> mDocument;
txOutputFormat mOutputFormat; txOutputFormat mOutputFormat;
}; };

Просмотреть файл

@ -39,6 +39,7 @@
#include "txMozillaXMLOutput.h" #include "txMozillaXMLOutput.h"
#include "nsIDocument.h" #include "nsIDocument.h"
#include "nsIDocShell.h"
#include "nsIDOMComment.h" #include "nsIDOMComment.h"
#include "nsIDOMDocumentType.h" #include "nsIDOMDocumentType.h"
#include "nsIDOMDOMImplementation.h" #include "nsIDOMDOMImplementation.h"
@ -48,31 +49,80 @@
#include "nsIDOMHTMLTableSectionElem.h" #include "nsIDOMHTMLTableSectionElem.h"
#include "nsIDOMHTMLScriptElement.h" #include "nsIDOMHTMLScriptElement.h"
#include "nsIDOMNSDocument.h" #include "nsIDOMNSDocument.h"
#include "nsIParser.h"
#include "nsIRefreshURI.h"
#include "nsIScriptGlobalObject.h"
#include "nsITextContent.h"
#include "nsIDocumentTransformer.h"
#include "nsIXMLContent.h"
#include "nsContentCID.h"
#include "nsNetUtil.h"
#include "nsUnicharUtils.h" #include "nsUnicharUtils.h"
#include "txAtoms.h" #include "txAtoms.h"
#include "nsIParser.h" #include "nsIDOMDocumentFragment.h"
#include "nsNetUtil.h"
#include "nsIScriptGlobalObject.h" static NS_DEFINE_CID(kXMLDocumentCID, NS_XMLDOCUMENT_CID);
#include "nsIRefreshURI.h" static NS_DEFINE_CID(kHTMLDocumentCID, NS_HTMLDOCUMENT_CID);
#include "nsIDocShell.h"
#define kXHTMLNameSpaceURI "http://www.w3.org/1999/xhtml" #define kXHTMLNameSpaceURI "http://www.w3.org/1999/xhtml"
#define kTXNameSpaceURI "http://www.mozilla.org/TransforMiix"
#define kTXWrapper "transformiix:result"
#define TX_ENSURE_CURRENTNODE \ #define TX_ENSURE_CURRENTNODE \
NS_ASSERTION(mCurrentNode, "mCurrentNode is NULL"); \ NS_ASSERTION(mCurrentNode, "mCurrentNode is NULL"); \
if (!mCurrentNode) \ if (!mCurrentNode) \
return return
txMozillaXMLOutput::txMozillaXMLOutput() : mDisableStylesheetLoad(PR_FALSE) txMozillaXMLOutput::txMozillaXMLOutput(const String& aRootName,
PRInt32 aRootNsID,
txOutputFormat* aFormat,
nsIDOMDocument* aSourceDocument,
nsIDOMDocument* aResultDocument,
nsITransformObserver* aObserver)
: mStyleSheetCount(0),
mDontAddCurrent(PR_FALSE),
mHaveTitleElement(PR_FALSE),
mHaveBaseElement(PR_FALSE),
mInTransform(PR_FALSE),
mCreatingNewDocument(PR_TRUE)
{ {
NS_INIT_ISUPPORTS();
mOutputFormat.merge(*aFormat);
mOutputFormat.setFromDefaults();
mObserver = do_GetWeakReference(aObserver);
createResultDocument(aRootName, aRootNsID, aSourceDocument, aResultDocument);
}
txMozillaXMLOutput::txMozillaXMLOutput(txOutputFormat* aFormat,
nsIDOMDocumentFragment* aFragment)
: mStyleSheetCount(0),
mDontAddCurrent(PR_FALSE),
mHaveTitleElement(PR_FALSE),
mHaveBaseElement(PR_FALSE),
mInTransform(PR_FALSE),
mCreatingNewDocument(PR_FALSE)
{
NS_INIT_ISUPPORTS();
mOutputFormat.merge(*aFormat);
mOutputFormat.setFromDefaults();
aFragment->GetOwnerDocument(getter_AddRefs(mDocument));
nsCOMPtr<nsIDocument> doc = do_QueryInterface(mDocument);
NS_ASSERTION(doc, "can't QI to nsIDocument");
doc->GetNameSpaceManager(*getter_AddRefs(mNameSpaceManager));
NS_ASSERTION(mNameSpaceManager, "Can't get namespace manager.");
mCurrentNode = aFragment;
} }
txMozillaXMLOutput::~txMozillaXMLOutput() txMozillaXMLOutput::~txMozillaXMLOutput()
{ {
} }
NS_IMPL_ISUPPORTS2(txMozillaXMLOutput,
txIOutputXMLEventHandler,
nsIScriptLoaderObserver);
void txMozillaXMLOutput::attribute(const String& aName, void txMozillaXMLOutput::attribute(const String& aName,
const PRInt32 aNsID, const PRInt32 aNsID,
const String& aValue) const String& aValue)
@ -118,22 +168,16 @@ void txMozillaXMLOutput::comment(const String& aData)
nsresult rv = mDocument->CreateComment(aData, nsresult rv = mDocument->CreateComment(aData,
getter_AddRefs(comment)); getter_AddRefs(comment));
NS_ASSERTION(NS_SUCCEEDED(rv), "Can't create comment"); NS_ASSERTION(NS_SUCCEEDED(rv), "Can't create comment");
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(comment);
nsCOMPtr<nsIDOMNode> resultNode; nsCOMPtr<nsIDOMNode> resultNode;
rv = mCurrentNode->AppendChild(node, getter_AddRefs(resultNode)); rv = mCurrentNode->AppendChild(comment, getter_AddRefs(resultNode));
NS_ASSERTION(NS_SUCCEEDED(rv), "Can't append comment"); NS_ASSERTION(NS_SUCCEEDED(rv), "Can't append comment");
} }
void txMozillaXMLOutput::disableStylesheetLoad()
{
mDisableStylesheetLoad = PR_TRUE;
}
void txMozillaXMLOutput::endDocument() void txMozillaXMLOutput::endDocument()
{ {
closePrevious(eCloseElement | eFlushText); closePrevious(eCloseElement | eFlushText);
if (!mHaveTitleElement) { // This should really be handled by nsIDocument::Reset
if (mCreatingNewDocument && !mHaveTitleElement) {
nsCOMPtr<nsIDOMNSDocument> domDoc = do_QueryInterface(mDocument); nsCOMPtr<nsIDOMNSDocument> domDoc = do_QueryInterface(mDocument);
if (domDoc) { if (domDoc) {
domDoc->SetTitle(NS_LITERAL_STRING("")); domDoc->SetTitle(NS_LITERAL_STRING(""));
@ -155,10 +199,15 @@ void txMozillaXMLOutput::endDocument()
} }
} }
} }
mInTransform = PR_FALSE;
SignalTransformEnd();
} }
void txMozillaXMLOutput::endElement(const String& aName, const PRInt32 aNsID) void txMozillaXMLOutput::endElement(const String& aName, const PRInt32 aNsID)
{ {
TX_ENSURE_CURRENTNODE;
#ifdef DEBUG #ifdef DEBUG
nsAutoString nodeName; nsAutoString nodeName;
mCurrentNode->GetNodeName(nodeName); mCurrentNode->GetNodeName(nodeName);
@ -204,21 +253,10 @@ void txMozillaXMLOutput::endElement(const String& aName, const PRInt32 aNsID)
} }
} }
nsresult txMozillaXMLOutput::getRootContent(nsIContent** aReturn) void txMozillaXMLOutput::getOutputDocument(nsIDOMDocument** aDocument)
{ {
NS_ASSERTION(aReturn, "NULL pointer passed to getRootContent"); *aDocument = mDocument;
NS_IF_ADDREF(*aDocument);
*aReturn = mRootContent;
NS_IF_ADDREF(*aReturn);
return NS_OK;
}
PRBool txMozillaXMLOutput::isDone()
{
PRUint32 scriptCount = 0;
if (mScriptElements)
mScriptElements->Count(&scriptCount);
return (scriptCount == 0);
} }
void txMozillaXMLOutput::processingInstruction(const String& aTarget, const String& aData) void txMozillaXMLOutput::processingInstruction(const String& aTarget, const String& aData)
@ -234,24 +272,30 @@ void txMozillaXMLOutput::processingInstruction(const String& aTarget, const Stri
nsresult rv = mDocument->CreateProcessingInstruction(aTarget, aData, nsresult rv = mDocument->CreateProcessingInstruction(aTarget, aData,
getter_AddRefs(pi)); getter_AddRefs(pi));
NS_ASSERTION(NS_SUCCEEDED(rv), "Can't create processing instruction"); NS_ASSERTION(NS_SUCCEEDED(rv), "Can't create processing instruction");
if (NS_FAILED(rv))
return;
nsCOMPtr<nsIStyleSheetLinkingElement> ssle = do_QueryInterface(pi); nsCOMPtr<nsIStyleSheetLinkingElement> ssle;
if (ssle) { if (mCreatingNewDocument) {
ssle->InitStyleLinkElement(nsnull, PR_FALSE); ssle = do_QueryInterface(pi);
ssle->SetEnableUpdates(PR_FALSE); if (ssle) {
ssle->InitStyleLinkElement(nsnull, PR_FALSE);
ssle->SetEnableUpdates(PR_FALSE);
}
} }
nsCOMPtr<nsIDOMNode> resultNode; nsCOMPtr<nsIDOMNode> resultNode;
mCurrentNode->AppendChild(pi, getter_AddRefs(resultNode)); rv = mCurrentNode->AppendChild(pi, getter_AddRefs(resultNode));
NS_ASSERTION(NS_SUCCEEDED(rv), "Can't append processing instruction"); NS_ASSERTION(NS_SUCCEEDED(rv), "Can't append processing instruction");
if (NS_FAILED(rv)) if (NS_FAILED(rv))
return; return;
if (ssle) { if (ssle) {
ssle->SetEnableUpdates(PR_TRUE); ssle->SetEnableUpdates(PR_TRUE);
rv = ssle->UpdateStyleSheet(nsnull, mStyleSheetCount); rv = ssle->UpdateStyleSheet(nsnull, mStyleSheetCount);
if (NS_SUCCEEDED(rv) || (rv == NS_ERROR_HTMLPARSER_BLOCK)) if (NS_SUCCEEDED(rv) || (rv == NS_ERROR_HTMLPARSER_BLOCK)) {
mStyleSheetCount++; mStyleSheetCount++;
}
} }
} }
@ -264,102 +308,54 @@ void txMozillaXMLOutput::removeScriptElement(nsIDOMHTMLScriptElement *aElement)
} }
} }
void txMozillaXMLOutput::setOutputDocument(nsIDOMDocument* aDocument)
{
NS_ASSERTION(aDocument, "Document can't be NULL!");
if (!aDocument)
return;
mDocument = aDocument;
mCurrentNode = mDocument;
mStyleSheetCount = 0;
mHaveTitleElement = PR_FALSE;
mHaveBaseElement = PR_FALSE;
mNonAddedParent = nsnull;
mNonAddedNode = nsnull;
mRefreshString.Truncate();
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDocument);
doc->GetNameSpaceManager(*getter_AddRefs(mNameSpaceManager));
NS_ASSERTION(mNameSpaceManager, "Can't get namespace manager.");
}
void txMozillaXMLOutput::setOutputFormat(txOutputFormat* aOutputFormat)
{
mOutputFormat.reset();
mOutputFormat.merge(*aOutputFormat);
mOutputFormat.setFromDefaults();
}
void txMozillaXMLOutput::startDocument() void txMozillaXMLOutput::startDocument()
{ {
NS_ASSERTION(mDocument, "Document can't be NULL!"); mInTransform = PR_TRUE;
} }
void txMozillaXMLOutput::startElement(const String& aName, void txMozillaXMLOutput::startElement(const String& aName,
const PRInt32 aNsID) const PRInt32 aNsID)
{ {
TX_ENSURE_CURRENTNODE;
closePrevious(eCloseElement | eFlushText); closePrevious(eCloseElement | eFlushText);
nsresult rv; nsresult rv;
if (!mRootContent && !mOutputFormat.mSystemId.isEmpty()) {
// No root element yet, so add the doctype if necesary.
nsCOMPtr<nsIDOMDOMImplementation> implementation;
rv = mDocument->GetImplementation(getter_AddRefs(implementation));
NS_ASSERTION(NS_SUCCEEDED(rv), "Can't get DOMImplementation");
if (NS_SUCCEEDED(rv)) {
nsAutoString qName;
nsCOMPtr<nsIDOMDocumentType> documentType;
nsCOMPtr<nsIDOMNode> firstNode, node;
if (mOutputFormat.mMethod == eHTMLOutput)
qName.Assign(NS_LITERAL_STRING("html"));
else
qName.Assign(aName);
rv = implementation->CreateDocumentType(qName,
mOutputFormat.mPublicId,
mOutputFormat.mSystemId,
getter_AddRefs(documentType));
NS_ASSERTION(NS_SUCCEEDED(rv), "Can't create doctype");
mDocument->GetFirstChild(getter_AddRefs(firstNode));
rv = mDocument->InsertBefore(documentType, firstNode, getter_AddRefs(node));
NS_ASSERTION(NS_SUCCEEDED(rv), "Can't insert doctype");
}
}
nsCOMPtr<nsIDOMElement> element; nsCOMPtr<nsIDOMElement> element;
mDontAddCurrent = PR_FALSE; mDontAddCurrent = PR_FALSE;
if ((mOutputFormat.mMethod == eHTMLOutput) && (aNsID == kNameSpaceID_None)) { if ((mOutputFormat.mMethod == eHTMLOutput) && (aNsID == kNameSpaceID_None)) {
// Outputting HTML as XHTML, lowercase element names rv = mDocument->CreateElement(aName,
nsAutoString lowerName(aName); getter_AddRefs(element));
ToLowerCase(lowerName); if (NS_FAILED(rv)) {
rv = mDocument->CreateElementNS(NS_LITERAL_STRING(kXHTMLNameSpaceURI), lowerName, return;
getter_AddRefs(element)); }
NS_ASSERTION(NS_SUCCEEDED(rv), "Can't create element");
startHTMLElement(element); startHTMLElement(element);
} }
else { else {
nsAutoString nsURI; nsAutoString nsURI;
mNameSpaceManager->GetNameSpaceURI(aNsID, nsURI); mNameSpaceManager->GetNameSpaceURI(aNsID, nsURI);
rv = mDocument->CreateElementNS(nsURI, aName, getter_AddRefs(element)); rv = mDocument->CreateElementNS(nsURI, aName,
getter_AddRefs(element));
NS_ASSERTION(NS_SUCCEEDED(rv), "Can't create element"); NS_ASSERTION(NS_SUCCEEDED(rv), "Can't create element");
if (NS_FAILED(rv)) {
return;
}
if (aNsID == kNameSpaceID_XHTML) if (aNsID == kNameSpaceID_XHTML)
startHTMLElement(element); startHTMLElement(element);
} }
if (element) { if (mCreatingNewDocument) {
nsCOMPtr<nsIContent> cont = do_QueryInterface(element); nsCOMPtr<nsIContent> cont = do_QueryInterface(element);
if (cont) { NS_ASSERTION(cont, "element doesn't implement nsIContent");
nsCOMPtr<nsIDocument> doc = do_QueryInterface(mDocument); nsCOMPtr<nsIDocument> doc = do_QueryInterface(mDocument);
cont->SetDocument(doc, PR_FALSE, PR_TRUE); cont->SetDocument(doc, PR_FALSE, PR_TRUE);
}
mParentNode = mCurrentNode;
mCurrentNode = do_QueryInterface(element);
} }
mParentNode = mCurrentNode;
mCurrentNode = do_QueryInterface(element);
} }
void txMozillaXMLOutput::closePrevious(PRInt8 aAction) void txMozillaXMLOutput::closePrevious(PRInt8 aAction)
@ -367,11 +363,6 @@ void txMozillaXMLOutput::closePrevious(PRInt8 aAction)
TX_ENSURE_CURRENTNODE; TX_ENSURE_CURRENTNODE;
nsresult rv; nsresult rv;
PRInt32 namespaceID = kNameSpaceID_None;
nsCOMPtr<nsIContent> currentContent = do_QueryInterface(mCurrentNode);
if (currentContent)
currentContent->GetNameSpaceID(namespaceID);
if ((aAction & eCloseElement) && mParentNode) { if ((aAction & eCloseElement) && mParentNode) {
nsCOMPtr<nsIDocument> document = do_QueryInterface(mParentNode); nsCOMPtr<nsIDocument> document = do_QueryInterface(mParentNode);
nsCOMPtr<nsIDOMElement> currentElement = do_QueryInterface(mCurrentNode); nsCOMPtr<nsIDOMElement> currentElement = do_QueryInterface(mCurrentNode);
@ -446,16 +437,18 @@ void txMozillaXMLOutput::startHTMLElement(nsIDOMElement* aElement)
mDontAddCurrent = (atom == txHTMLAtoms::script); mDontAddCurrent = (atom == txHTMLAtoms::script);
nsCOMPtr<nsIStyleSheetLinkingElement> ssle = if (mCreatingNewDocument) {
do_QueryInterface(aElement); nsCOMPtr<nsIStyleSheetLinkingElement> ssle =
if (ssle) { do_QueryInterface(aElement);
// XXX Trick nsCSSLoader into blocking/notifying us? if (ssle) {
// We would need to implement nsIParser and // XXX Trick nsCSSLoader into blocking/notifying us?
// pass ourselves as first parameter to // We would need to implement nsIParser and
// InitStyleLinkElement. We would then be notified // pass ourselves as first parameter to
// of stylesheet loads/load failures. // InitStyleLinkElement. We would then be notified
ssle->InitStyleLinkElement(nsnull, PR_FALSE); // of stylesheet loads/load failures.
ssle->SetEnableUpdates(PR_FALSE); ssle->InitStyleLinkElement(nsnull, PR_FALSE);
ssle->SetEnableUpdates(PR_FALSE);
}
} }
} }
@ -503,7 +496,8 @@ void txMozillaXMLOutput::endHTMLElement(nsIDOMElement* aElement,
} }
} }
// Load scripts // Load scripts
else if (atom == txHTMLAtoms::script) { else if (mCreatingNewDocument &&
atom == txHTMLAtoms::script) {
// Add this script element to the array of loading script elements. // Add this script element to the array of loading script elements.
nsCOMPtr<nsIDOMHTMLScriptElement> scriptElement = nsCOMPtr<nsIDOMHTMLScriptElement> scriptElement =
do_QueryInterface(mCurrentNode); do_QueryInterface(mCurrentNode);
@ -515,7 +509,8 @@ void txMozillaXMLOutput::endHTMLElement(nsIDOMElement* aElement,
mScriptElements->AppendElement(scriptElement); mScriptElements->AppendElement(scriptElement);
} }
// Set document title // Set document title
else if (atom == txHTMLAtoms::title && !mHaveTitleElement) { else if (mCreatingNewDocument &&
atom == txHTMLAtoms::title && !mHaveTitleElement) {
// The first title wins // The first title wins
mHaveTitleElement = PR_TRUE; mHaveTitleElement = PR_TRUE;
nsCOMPtr<nsIDOMNSDocument> domDoc = do_QueryInterface(mDocument); nsCOMPtr<nsIDOMNSDocument> domDoc = do_QueryInterface(mDocument);
@ -528,7 +523,8 @@ void txMozillaXMLOutput::endHTMLElement(nsIDOMElement* aElement,
domDoc->SetTitle(text); domDoc->SetTitle(text);
} }
} }
else if (atom == txHTMLAtoms::base && !mHaveBaseElement) { else if (mCreatingNewDocument &&
atom == txHTMLAtoms::base && !mHaveBaseElement) {
// The first base wins // The first base wins
mHaveBaseElement = PR_TRUE; mHaveBaseElement = PR_TRUE;
@ -545,7 +541,8 @@ void txMozillaXMLOutput::endHTMLElement(nsIDOMElement* aElement,
return; return;
doc->SetBaseURL(baseURI); // The document checks if it is legal to set this base doc->SetBaseURL(baseURI); // The document checks if it is legal to set this base
} }
else if (atom == txHTMLAtoms::meta) { else if (mCreatingNewDocument &&
atom == txHTMLAtoms::meta) {
// handle HTTP-EQUIV data // handle HTTP-EQUIV data
nsAutoString httpEquiv; nsAutoString httpEquiv;
content->GetAttr(kNameSpaceID_None, txHTMLAtoms::httpEquiv, httpEquiv); content->GetAttr(kNameSpaceID_None, txHTMLAtoms::httpEquiv, httpEquiv);
@ -563,7 +560,7 @@ void txMozillaXMLOutput::endHTMLElement(nsIDOMElement* aElement,
} }
// Handle all sorts of stylesheets // Handle all sorts of stylesheets
if (!mDisableStylesheetLoad) { if (mCreatingNewDocument) {
nsCOMPtr<nsIStyleSheetLinkingElement> ssle = nsCOMPtr<nsIStyleSheetLinkingElement> ssle =
do_QueryInterface(aElement); do_QueryInterface(aElement);
if (ssle) { if (ssle) {
@ -603,3 +600,168 @@ void txMozillaXMLOutput::wrapChildren(nsIDOMNode* aCurrentNode,
} }
} }
} }
nsresult
txMozillaXMLOutput::createResultDocument(const String& aName, PRInt32 aNsID,
nsIDOMDocument* aSourceDocument,
nsIDOMDocument* aResultDocument)
{
nsresult rv;
nsCOMPtr<nsIDocument> doc;
if (!aResultDocument) {
// Create the document
if (mOutputFormat.mMethod == eHTMLOutput) {
doc = do_CreateInstance(kHTMLDocumentCID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
}
else {
// We should check the root name/namespace here and create the
// appropriate document
doc = do_CreateInstance(kXMLDocumentCID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
}
mDocument = do_QueryInterface(doc);
}
else {
mDocument = aResultDocument;
doc = do_QueryInterface(aResultDocument);
}
mCurrentNode = mDocument;
doc->GetNameSpaceManager(*getter_AddRefs(mNameSpaceManager));
NS_ASSERTION(mNameSpaceManager, "Can't get namespace manager.");
// Reset and set up the document
nsCOMPtr<nsILoadGroup> loadGroup;
nsCOMPtr<nsIChannel> channel;
nsCOMPtr<nsIDocument> sourceDoc = do_QueryInterface(aSourceDocument);
sourceDoc->GetDocumentLoadGroup(getter_AddRefs(loadGroup));
nsCOMPtr<nsIIOService> serv = do_GetService(NS_IOSERVICE_CONTRACTID);
if (serv) {
// Create a temporary channel to get nsIDocument->Reset to
// do the right thing. We want the output document to get
// much of the input document's characteristics.
nsCOMPtr<nsIURI> docURL;
sourceDoc->GetDocumentURL(getter_AddRefs(docURL));
serv->NewChannelFromURI(docURL, getter_AddRefs(channel));
}
doc->Reset(channel, loadGroup);
nsCOMPtr<nsIURI> baseURL;
sourceDoc->GetBaseURL(*getter_AddRefs(baseURL));
doc->SetBaseURL(baseURL);
// XXX We might want to call SetDefaultStylesheets here
// Set up script loader of the result document.
nsCOMPtr<nsIScriptLoader> loader;
doc->GetScriptLoader(getter_AddRefs(loader));
nsCOMPtr<nsITransformObserver> observer = do_QueryReferent(mObserver);
if (loader) {
if (observer) {
loader->AddObserver(this);
}
else {
// Don't load scripts, we can't notify the caller when they're loaded.
loader->SetEnabled(PR_FALSE);
}
}
// Notify the contentsink that the document is created
if (observer) {
observer->OnDocumentCreated(mDocument);
}
// Add a doc-type if requested
if (!mOutputFormat.mSystemId.isEmpty()) {
nsCOMPtr<nsIDOMDOMImplementation> implementation;
rv = aSourceDocument->GetImplementation(getter_AddRefs(implementation));
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString qName;
if (mOutputFormat.mMethod == eHTMLOutput) {
qName.Assign(NS_LITERAL_STRING("html"));
}
else {
qName.Assign(aName.getConstNSString());
}
nsCOMPtr<nsIDOMDocumentType> documentType;
rv = implementation->CreateDocumentType(qName,
mOutputFormat.mPublicId,
mOutputFormat.mSystemId,
getter_AddRefs(documentType));
NS_ASSERTION(NS_SUCCEEDED(rv), "Can't create doctype");
nsCOMPtr<nsIDOMNode> tmp;
mDocument->AppendChild(documentType, getter_AddRefs(tmp));
}
return NS_OK;
}
NS_IMETHODIMP
txMozillaXMLOutput::ScriptAvailable(nsresult aResult,
nsIDOMHTMLScriptElement *aElement,
PRBool aIsInline,
PRBool aWasPending,
nsIURI *aURI,
PRInt32 aLineNo,
const nsAString& aScript)
{
if (NS_FAILED(aResult)) {
removeScriptElement(aElement);
SignalTransformEnd();
}
return NS_OK;
}
NS_IMETHODIMP
txMozillaXMLOutput::ScriptEvaluated(nsresult aResult,
nsIDOMHTMLScriptElement *aElement,
PRBool aIsInline,
PRBool aWasPending)
{
removeScriptElement(aElement);
SignalTransformEnd();
return NS_OK;
}
void
txMozillaXMLOutput::SignalTransformEnd()
{
if (mInTransform) {
return;
}
nsCOMPtr<nsITransformObserver> observer = do_QueryReferent(mObserver);
if (!observer) {
return;
}
if (mScriptElements) {
PRUint32 scriptCount = 0;
mScriptElements->Count(&scriptCount);
if (scriptCount != 0) {
return;
}
}
// Make sure that we don't get deleted while this function is executed and
// we remove ourselfs from the scriptloader
nsCOMPtr<nsIScriptLoaderObserver> kungFuDeathGrip(this);
mObserver = nsnull;
// XXX Need a better way to determine transform success/failure
if (mDocument) {
nsCOMPtr<nsIScriptLoader> loader;
nsCOMPtr<nsIDocument> doc = do_QueryInterface(mDocument);
doc->GetScriptLoader(getter_AddRefs(loader));
if (loader) {
loader->RemoveObserver(this);
}
observer->OnTransformDone(NS_OK, mDocument);
}
else {
// XXX Need better error message and code.
observer->OnTransformDone(NS_ERROR_FAILURE, nsnull);
}
}

Просмотреть файл

@ -44,17 +44,31 @@
#include "nsIDOMDocument.h" #include "nsIDOMDocument.h"
#include "nsIDOMHTMLTextAreaElement.h" #include "nsIDOMHTMLTextAreaElement.h"
#include "nsINameSpaceManager.h" #include "nsINameSpaceManager.h"
#include "nsIScriptLoader.h"
#include "nsIScriptLoaderObserver.h"
#include "nsIStyleSheetLinkingElement.h" #include "nsIStyleSheetLinkingElement.h"
#include "nsString.h" #include "nsString.h"
#include "nsSupportsArray.h" #include "nsSupportsArray.h"
#include "nsWeakPtr.h"
#include "txOutputFormat.h" #include "txOutputFormat.h"
class txMozillaXMLOutput : public txMozillaXMLEventHandler class txMozillaXMLOutput : public txIOutputXMLEventHandler,
public nsIScriptLoaderObserver
{ {
public: public:
txMozillaXMLOutput(); txMozillaXMLOutput(const String& aRootName,
PRInt32 aRootNsID,
txOutputFormat* aFormat,
nsIDOMDocument* aSourceDocument,
nsIDOMDocument* aResultDocument,
nsITransformObserver* aObserver);
txMozillaXMLOutput(txOutputFormat* aFormat,
nsIDOMDocumentFragment* aFragment);
virtual ~txMozillaXMLOutput(); virtual ~txMozillaXMLOutput();
NS_DECL_ISUPPORTS
NS_DECL_NSISCRIPTLOADEROBSERVER
/** /**
* Signals to receive the start of an attribute. * Signals to receive the start of an attribute.
* *
@ -73,6 +87,16 @@ public:
*/ */
void characters(const String& aData); void characters(const String& aData);
/**
* Signals to receive characters that don't need output escaping.
*
* @param aData the characters to receive
*/
void charactersNoOutputEscaping(const String& aData)
{
NS_ASSERTION(0, "Don't call this in module, we don't do d-o-e");
}
/** /**
* Signals to receive data that should be treated as a comment. * Signals to receive data that should be treated as a comment.
* *
@ -95,6 +119,18 @@ public:
void endElement(const String& aName, void endElement(const String& aName,
const PRInt32 aNsID); const PRInt32 aNsID);
/**
* Returns whether the output handler supports
* disable-output-escaping.
*
* @return MB_TRUE if this handler supports
* disable-output-escaping
*/
MBool hasDisableOutputEscaping()
{
return MB_FALSE;
}
/** /**
* Signals to receive a processing instruction. * Signals to receive a processing instruction.
* *
@ -118,31 +154,6 @@ public:
void startElement(const String& aName, void startElement(const String& aName,
const PRInt32 aNsID); const PRInt32 aNsID);
/**
* Sets the output format.
*
* @param aOutputFormat the output format
*/
void setOutputFormat(txOutputFormat* aOutputFormat);
/**
* Disables loading of stylesheets.
*/
void disableStylesheetLoad();
/**
* Returns the root content of the result.
*
* @param aReturn the root content
*/
nsresult getRootContent(nsIContent** aReturn);
/**
* Returns PR_TRUE if the event handler has finished anything
* extra that had to happen after the transform has finished.
*/
PRBool isDone();
/** /**
* Removes a script element from the array of elements that are * Removes a script element from the array of elements that are
* still loading. * still loading.
@ -152,11 +163,11 @@ public:
void removeScriptElement(nsIDOMHTMLScriptElement *aElement); void removeScriptElement(nsIDOMHTMLScriptElement *aElement);
/** /**
* Sets the Mozilla output document. * Gets the Mozilla output document
* *
* @param aDocument the Mozilla output document * @param aDocument the Mozilla output document
*/ */
void setOutputDocument(nsIDOMDocument* aDocument); void getOutputDocument(nsIDOMDocument** aDocument);
private: private:
void closePrevious(PRInt8 aAction); void closePrevious(PRInt8 aAction);
@ -164,11 +175,16 @@ private:
void endHTMLElement(nsIDOMElement* aElement, PRBool aXHTML); void endHTMLElement(nsIDOMElement* aElement, PRBool aXHTML);
void processHTTPEquiv(nsIAtom* aHeader, const nsAString& aValue); void processHTTPEquiv(nsIAtom* aHeader, const nsAString& aValue);
void wrapChildren(nsIDOMNode* aCurrentNode, nsIDOMElement* aWrapper); void wrapChildren(nsIDOMNode* aCurrentNode, nsIDOMElement* aWrapper);
nsresult createResultDocument(const String& aName, PRInt32 aNsID,
nsIDOMDocument* aSourceDocument,
nsIDOMDocument* aResultDocument);
void SignalTransformEnd();
nsCOMPtr<nsIDOMDocument> mDocument; nsCOMPtr<nsIDOMDocument> mDocument;
nsCOMPtr<nsIDOMNode> mCurrentNode; nsCOMPtr<nsIDOMNode> mCurrentNode;
nsCOMPtr<nsIDOMNode> mParentNode; nsCOMPtr<nsIDOMNode> mParentNode;
nsCOMPtr<nsIContent> mRootContent; nsCOMPtr<nsIContent> mRootContent;
nsWeakPtr mObserver;
nsCOMPtr<nsIDOMNode> mNonAddedParent; nsCOMPtr<nsIDOMNode> mNonAddedParent;
nsCOMPtr<nsIDOMNode> mNonAddedNode; nsCOMPtr<nsIDOMNode> mNonAddedNode;
@ -184,12 +200,14 @@ private:
txOutputFormat mOutputFormat; txOutputFormat mOutputFormat;
PRPackedBool mDisableStylesheetLoad;
PRPackedBool mDontAddCurrent; PRPackedBool mDontAddCurrent;
PRPackedBool mHaveTitleElement; PRPackedBool mHaveTitleElement;
PRPackedBool mHaveBaseElement; PRPackedBool mHaveBaseElement;
PRPackedBool mInTransform;
PRPackedBool mCreatingNewDocument;
enum txAction { eCloseElement = 1, eFlushText = 2 }; enum txAction { eCloseElement = 1, eFlushText = 2 };
}; };

Просмотреть файл

@ -0,0 +1,768 @@
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Van der Beken <peterv@netscape.com> (original author)
*
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "txMozillaXSLTProcessor.h"
#include "nsContentCID.h"
#include "nsDOMError.h"
#include "nsIContent.h"
#include "nsIDocument.h"
#include "nsIDOMClassInfo.h"
#include "nsIScriptLoader.h"
#include "nsNetUtil.h"
#include "ProcessorState.h"
#include "txMozillaTextOutput.h"
#include "txMozillaXMLOutput.h"
#include "txSingleNodeContext.h"
#include "txURIUtils.h"
#include "XMLUtils.h"
#include "txUnknownHandler.h"
#include "nsIHTMLDocument.h"
/**
* Output Handler Factories
*/
class txToDocHandlerFactory : public txIOutputHandlerFactory
{
public:
txToDocHandlerFactory(ProcessorState* aPs,
nsIDOMDocument* aSourceDocument,
nsIDOMDocument* aResultDocument,
nsITransformObserver* aObserver)
: mPs(aPs), mSourceDocument(aSourceDocument),
mResultDocument(aResultDocument), mObserver(aObserver)
{
}
virtual ~txToDocHandlerFactory()
{
}
TX_DECL_TXIOUTPUTHANDLERFACTORY;
private:
ProcessorState* mPs;
nsCOMPtr<nsIDOMDocument> mSourceDocument;
nsCOMPtr<nsIDOMDocument> mResultDocument;
nsCOMPtr<nsITransformObserver> mObserver;
};
class txToFragmentHandlerFactory : public txIOutputHandlerFactory
{
public:
txToFragmentHandlerFactory(nsIDOMDocumentFragment* aFragment)
: mFragment(aFragment)
{
}
virtual ~txToFragmentHandlerFactory()
{
}
TX_DECL_TXIOUTPUTHANDLERFACTORY;
private:
nsCOMPtr<nsIDOMDocumentFragment> mFragment;
};
nsresult
txToDocHandlerFactory::createHandlerWith(txOutputFormat* aFormat,
txIOutputXMLEventHandler** aHandler)
{
*aHandler = nsnull;
switch (aFormat->mMethod) {
case eMethodNotSet:
case eXMLOutput:
{
*aHandler = new txUnknownHandler(mPs);
break;
}
case eHTMLOutput:
{
*aHandler = new txMozillaXMLOutput(String(), kNameSpaceID_None,
aFormat, mSourceDocument,
mResultDocument, mObserver);
break;
}
case eTextOutput:
{
*aHandler = new txMozillaTextOutput(mSourceDocument,
mResultDocument,
mObserver);
break;
}
}
NS_ENSURE_TRUE(*aHandler, NS_ERROR_OUT_OF_MEMORY);
return NS_OK;
}
nsresult
txToDocHandlerFactory::createHandlerWith(txOutputFormat* aFormat,
const String& aName,
PRInt32 aNsID,
txIOutputXMLEventHandler** aHandler)
{
*aHandler = nsnull;
switch (aFormat->mMethod) {
case eMethodNotSet:
{
NS_ERROR("How can method not be known when root element is?");
return NS_ERROR_UNEXPECTED;
}
case eXMLOutput:
case eHTMLOutput:
{
*aHandler = new txMozillaXMLOutput(aName, aNsID, aFormat,
mSourceDocument,
mResultDocument,
mObserver);
break;
}
case eTextOutput:
{
*aHandler = new txMozillaTextOutput(mSourceDocument,
mResultDocument,
mObserver);
break;
}
}
NS_ENSURE_TRUE(*aHandler, NS_ERROR_OUT_OF_MEMORY);
return NS_OK;
}
nsresult
txToFragmentHandlerFactory::createHandlerWith(txOutputFormat* aFormat,
txIOutputXMLEventHandler** aHandler)
{
*aHandler = nsnull;
switch (aFormat->mMethod) {
case eMethodNotSet:
{
txOutputFormat format;
format.merge(*aFormat);
nsCOMPtr<nsIDOMDocument> doc;
mFragment->GetOwnerDocument(getter_AddRefs(doc));
NS_ASSERTION(doc, "unable to get ownerdocument");
// Need a way for testing xhtml vs. html. But this is the best
// we can do for now.
nsCOMPtr<nsIHTMLDocument> htmldoc = do_QueryInterface(doc);
format.mMethod = htmldoc ? eHTMLOutput : eXMLOutput;
*aHandler = new txMozillaXMLOutput(&format, mFragment);
break;
}
case eXMLOutput:
case eHTMLOutput:
{
*aHandler = new txMozillaXMLOutput(aFormat, mFragment);
break;
}
case eTextOutput:
{
*aHandler = new txMozillaTextOutput(mFragment);
break;
}
}
NS_ENSURE_TRUE(*aHandler, NS_ERROR_OUT_OF_MEMORY);
return NS_OK;
}
nsresult
txToFragmentHandlerFactory::createHandlerWith(txOutputFormat* aFormat,
const String& aName,
PRInt32 aNsID,
txIOutputXMLEventHandler** aHandler)
{
*aHandler = nsnull;
NS_ASSERTION(aFormat->mMethod != eMethodNotSet,
"How can method not be known when root element is?");
NS_ENSURE_TRUE(aFormat->mMethod != eMethodNotSet, NS_ERROR_UNEXPECTED);
return createHandlerWith(aFormat, aHandler);
}
/**
* txMozillaXSLTProcessor
*/
NS_DEFINE_CID(kNameSpaceManagerCID, NS_NAMESPACEMANAGER_CID);
NS_IMPL_ADDREF(txMozillaXSLTProcessor)
NS_IMPL_RELEASE(txMozillaXSLTProcessor)
NS_INTERFACE_MAP_BEGIN(txMozillaXSLTProcessor)
NS_INTERFACE_MAP_ENTRY(nsIXSLTProcessor)
NS_INTERFACE_MAP_ENTRY(nsIXSLTProcessorObsolete)
NS_INTERFACE_MAP_ENTRY(nsIDocumentTransformer)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXSLTProcessor)
NS_INTERFACE_MAP_ENTRY_EXTERNAL_DOM_CLASSINFO(XSLTProcessor)
NS_INTERFACE_MAP_END
txMozillaXSLTProcessor::txMozillaXSLTProcessor() : mVariables(PR_TRUE)
{
NS_INIT_ISUPPORTS();
}
txMozillaXSLTProcessor::~txMozillaXSLTProcessor()
{
}
NS_IMETHODIMP
txMozillaXSLTProcessor::TransformDocument(nsIDOMNode* aSourceDOM,
nsIDOMNode* aStyleDOM,
nsIDOMDocument* aOutputDoc,
nsISupports* aObserver)
{
NS_ENSURE_ARG(aSourceDOM);
NS_ENSURE_ARG(aStyleDOM);
NS_ENSURE_ARG(aOutputDoc);
NS_ENSURE_FALSE(aObserver, NS_ERROR_NOT_IMPLEMENTED);
if (!URIUtils::CanCallerAccess(aSourceDOM) ||
!URIUtils::CanCallerAccess(aStyleDOM) ||
!URIUtils::CanCallerAccess(aOutputDoc)) {
return NS_ERROR_DOM_SECURITY_ERR;
}
// Create wrapper for the source document.
nsCOMPtr<nsIDOMDocument> sourceDOMDocument;
aSourceDOM->GetOwnerDocument(getter_AddRefs(sourceDOMDocument));
if (!sourceDOMDocument) {
sourceDOMDocument = do_QueryInterface(aSourceDOM);
NS_ENSURE_TRUE(sourceDOMDocument, NS_ERROR_FAILURE);
}
Document sourceDocument(sourceDOMDocument);
Node* sourceNode = sourceDocument.createWrapper(aSourceDOM);
NS_ENSURE_TRUE(sourceNode, NS_ERROR_FAILURE);
// Create wrapper for the style document.
nsCOMPtr<nsIDOMDocument> styleDOMDocument;
aStyleDOM->GetOwnerDocument(getter_AddRefs(styleDOMDocument));
if (!styleDOMDocument) {
styleDOMDocument = do_QueryInterface(aStyleDOM);
}
Document xslDocument(styleDOMDocument);
// Create a new ProcessorState. Must be done after creating the documents
// so that C++ will ensure that it is destroyed before the documents.
ProcessorState ps(&sourceDocument, &xslDocument);
// XXX Need to add error observers
// Set current txIEvalContext
txSingleNodeContext evalContext(&sourceDocument, &ps);
ps.setEvalContext(&evalContext);
// Index templates and process top level xslt elements
nsCOMPtr<nsIDOMDocument> styleDoc = do_QueryInterface(aStyleDOM);
nsresult rv;
if (styleDoc) {
rv = txXSLTProcessor::processStylesheet(&xslDocument,
&mVariables, &ps);
}
else {
nsCOMPtr<nsIDOMElement> styleElem = do_QueryInterface(aStyleDOM);
NS_ENSURE_TRUE(styleElem, NS_ERROR_FAILURE);
Element* element = xslDocument.createElement(styleElem);
NS_ENSURE_TRUE(element, NS_ERROR_OUT_OF_MEMORY);
rv = txXSLTProcessor::processTopLevel(element, &mVariables,
&ps);
}
NS_ENSURE_SUCCESS(rv, rv);
txToDocHandlerFactory handlerFactory(&ps, sourceDOMDocument, aOutputDoc,
nsnull);
ps.mOutputHandlerFactory = &handlerFactory;
// Process root of XML source document
txXSLTProcessor::transform(&ps);
return NS_OK;
}
NS_IMETHODIMP
txMozillaXSLTProcessor::TransformDocument(nsIDOMNode* aSourceDOM,
nsIDOMNode* aStyleDOM,
nsITransformObserver* aObserver,
nsIDOMDocument** aOutputDoc)
{
NS_ENSURE_ARG(aSourceDOM);
NS_ENSURE_ARG(aStyleDOM);
NS_ASSERTION(aObserver, "no observer");
NS_ENSURE_ARG_POINTER(aOutputDoc);
// Create wrapper for the source document.
nsCOMPtr<nsIDOMDocument> sourceDOMDocument;
aSourceDOM->GetOwnerDocument(getter_AddRefs(sourceDOMDocument));
if (!sourceDOMDocument) {
sourceDOMDocument = do_QueryInterface(aSourceDOM);
}
NS_ENSURE_TRUE(sourceDOMDocument, NS_ERROR_FAILURE);
Document sourceDocument(sourceDOMDocument);
Node* sourceNode = sourceDocument.createWrapper(aSourceDOM);
NS_ENSURE_TRUE(sourceNode, NS_ERROR_FAILURE);
// Create wrapper for the style document.
nsCOMPtr<nsIDOMDocument> styleDOMDocument;
aStyleDOM->GetOwnerDocument(getter_AddRefs(styleDOMDocument));
if (!styleDOMDocument) {
styleDOMDocument = do_QueryInterface(aStyleDOM);
}
Document xslDocument(styleDOMDocument);
// Create a new ProcessorState. Must be done after creating the documents
// so that C++ will ensure that it is destroyed before the documents.
ProcessorState ps(&sourceDocument, &xslDocument);
// XXX Need to add error observers
// Set current txIEvalContext
txSingleNodeContext evalContext(&sourceDocument, &ps);
ps.setEvalContext(&evalContext);
// Index templates and process top level xslt elements
nsCOMPtr<nsIDOMDocument> styleDoc = do_QueryInterface(aStyleDOM);
nsresult rv;
if (styleDoc) {
rv = txXSLTProcessor::processStylesheet(&xslDocument,
&mVariables, &ps);
}
else {
nsCOMPtr<nsIDOMElement> styleElem = do_QueryInterface(aStyleDOM);
NS_ENSURE_TRUE(styleElem, NS_ERROR_FAILURE);
Element* element = xslDocument.createElement(styleElem);
NS_ENSURE_TRUE(element, NS_ERROR_OUT_OF_MEMORY);
rv = txXSLTProcessor::processTopLevel(element, &mVariables,
&ps);
}
NS_ENSURE_SUCCESS(rv, rv);
txToDocHandlerFactory handlerFactory(&ps, sourceDOMDocument, nsnull,
aObserver);
ps.mOutputHandlerFactory = &handlerFactory;
// Process root of XML source document
txXSLTProcessor::transform(&ps);
ps.mOutputHandler->getOutputDocument(aOutputDoc);
return NS_OK;
}
NS_IMETHODIMP
txMozillaXSLTProcessor::ImportStylesheet(nsIDOMNode *aStyle)
{
if (!URIUtils::CanCallerAccess(aStyle)) {
return NS_ERROR_DOM_SECURITY_ERR;
}
if (mStylesheet) {
return NS_ERROR_NOT_IMPLEMENTED;
}
PRUint16 type = 0;
aStyle->GetNodeType(&type);
NS_ENSURE_TRUE(type == nsIDOMNode::ELEMENT_NODE ||
type == nsIDOMNode::DOCUMENT_NODE,
NS_ERROR_INVALID_ARG);
mStylesheet = aStyle;
return NS_OK;
}
NS_IMETHODIMP
txMozillaXSLTProcessor::TransformToDocument(nsIDOMNode *aSource,
nsIDOMDocument **aResult)
{
NS_ENSURE_ARG(aSource);
NS_ENSURE_ARG_POINTER(aResult);
NS_ENSURE_TRUE(mStylesheet, NS_ERROR_NOT_INITIALIZED);
if (!URIUtils::CanCallerAccess(aSource)) {
return NS_ERROR_DOM_SECURITY_ERR;
}
// Create wrapper for the source document.
nsCOMPtr<nsIDOMDocument> sourceDOMDocument;
aSource->GetOwnerDocument(getter_AddRefs(sourceDOMDocument));
if (!sourceDOMDocument) {
sourceDOMDocument = do_QueryInterface(aSource);
}
NS_ENSURE_TRUE(sourceDOMDocument, NS_ERROR_FAILURE);
Document sourceDocument(sourceDOMDocument);
Node* sourceNode = sourceDocument.createWrapper(aSource);
NS_ENSURE_TRUE(sourceNode, NS_ERROR_FAILURE);
// Create wrapper for the style document.
nsCOMPtr<nsIDOMDocument> styleDOMDocument;
mStylesheet->GetOwnerDocument(getter_AddRefs(styleDOMDocument));
if (!styleDOMDocument) {
styleDOMDocument = do_QueryInterface(mStylesheet);
}
Document xslDocument(styleDOMDocument);
// Create a new ProcessorState. Must be done after creating the documents
// so that C++ will ensure that it is destroyed before the documents.
ProcessorState ps(&sourceDocument, &xslDocument);
// XXX Need to add error observers
// Set current txIEvalContext
txSingleNodeContext evalContext(&sourceDocument, &ps);
ps.setEvalContext(&evalContext);
// Index templates and process top level xslt elements
nsCOMPtr<nsIDOMDocument> styleDoc = do_QueryInterface(mStylesheet);
nsresult rv;
if (styleDoc) {
rv = txXSLTProcessor::processStylesheet(&xslDocument,
&mVariables, &ps);
}
else {
nsCOMPtr<nsIDOMElement> styleElem = do_QueryInterface(mStylesheet);
NS_ENSURE_TRUE(styleElem, NS_ERROR_FAILURE);
Element* element = xslDocument.createElement(styleElem);
NS_ENSURE_TRUE(element, NS_ERROR_OUT_OF_MEMORY);
rv = txXSLTProcessor::processTopLevel(element, &mVariables,
&ps);
}
NS_ENSURE_SUCCESS(rv, rv);
txToDocHandlerFactory handlerFactory(&ps, sourceDOMDocument, nsnull,
nsnull);
ps.mOutputHandlerFactory = &handlerFactory;
// Process root of XML source document
txXSLTProcessor::transform(&ps);
ps.mOutputHandler->getOutputDocument(aResult);
return NS_OK;
}
NS_IMETHODIMP
txMozillaXSLTProcessor::TransformToFragment(nsIDOMNode *aSource,
nsIDOMDocument *aOutput,
nsIDOMDocumentFragment **aResult)
{
NS_ENSURE_ARG(aSource);
NS_ENSURE_ARG(aOutput);
NS_ENSURE_ARG_POINTER(aResult);
NS_ENSURE_TRUE(mStylesheet, NS_ERROR_NOT_INITIALIZED);
if (!URIUtils::CanCallerAccess(aSource) ||
!URIUtils::CanCallerAccess(aOutput)) {
return NS_ERROR_DOM_SECURITY_ERR;
}
// Create wrapper for the source document.
nsCOMPtr<nsIDOMDocument> sourceDOMDocument;
aSource->GetOwnerDocument(getter_AddRefs(sourceDOMDocument));
if (!sourceDOMDocument) {
sourceDOMDocument = do_QueryInterface(aSource);
}
NS_ENSURE_TRUE(sourceDOMDocument, NS_ERROR_FAILURE);
Document sourceDocument(sourceDOMDocument);
Node* sourceNode = sourceDocument.createWrapper(aSource);
NS_ENSURE_TRUE(sourceNode, NS_ERROR_FAILURE);
// Create wrapper for the style document.
nsCOMPtr<nsIDOMDocument> styleDOMDocument;
mStylesheet->GetOwnerDocument(getter_AddRefs(styleDOMDocument));
if (!styleDOMDocument) {
styleDOMDocument = do_QueryInterface(mStylesheet);
}
Document xslDocument(styleDOMDocument);
// Create a new ProcessorState. Must be done after creating the documents
// so that C++ will ensure that it is destroyed before the documents.
ProcessorState ps(&sourceDocument, &xslDocument);
// XXX Need to add error observers
// Set current txIEvalContext
txSingleNodeContext evalContext(&sourceDocument, &ps);
ps.setEvalContext(&evalContext);
// Index templates and process top level xslt elements
nsCOMPtr<nsIDOMDocument> styleDoc = do_QueryInterface(mStylesheet);
nsresult rv;
if (styleDoc) {
rv = txXSLTProcessor::processStylesheet(&xslDocument,
&mVariables, &ps);
}
else {
nsCOMPtr<nsIDOMElement> styleElem = do_QueryInterface(mStylesheet);
NS_ENSURE_TRUE(styleElem, NS_ERROR_FAILURE);
Element* element = xslDocument.createElement(styleElem);
NS_ENSURE_TRUE(element, NS_ERROR_OUT_OF_MEMORY);
rv = txXSLTProcessor::processTopLevel(element, &mVariables,
&ps);
}
NS_ENSURE_SUCCESS(rv, rv);
rv = aOutput->CreateDocumentFragment(aResult);
NS_ENSURE_SUCCESS(rv, rv);
txToFragmentHandlerFactory handlerFactory(*aResult);
ps.mOutputHandlerFactory = &handlerFactory;
// Process root of XML source document
txXSLTProcessor::transform(&ps);
return NS_OK;
}
NS_IMETHODIMP
txMozillaXSLTProcessor::SetParameter(const nsAString & aNamespaceURI,
const nsAString & aLocalName,
nsIVariant *aValue)
{
NS_ENSURE_ARG(aValue);
PRUint16 dataType;
aValue->GetDataType(&dataType);
switch (dataType) {
// Number
case nsIDataType::VTYPE_INT8:
case nsIDataType::VTYPE_INT16:
case nsIDataType::VTYPE_INT32:
case nsIDataType::VTYPE_INT64:
case nsIDataType::VTYPE_UINT8:
case nsIDataType::VTYPE_UINT16:
case nsIDataType::VTYPE_UINT32:
case nsIDataType::VTYPE_UINT64:
case nsIDataType::VTYPE_FLOAT:
case nsIDataType::VTYPE_DOUBLE:
// Boolean
case nsIDataType::VTYPE_BOOL:
// String
case nsIDataType::VTYPE_CHAR:
case nsIDataType::VTYPE_WCHAR:
case nsIDataType::VTYPE_DOMSTRING:
case nsIDataType::VTYPE_CHAR_STR:
case nsIDataType::VTYPE_WCHAR_STR:
case nsIDataType::VTYPE_STRING_SIZE_IS:
case nsIDataType::VTYPE_WSTRING_SIZE_IS:
case nsIDataType::VTYPE_UTF8STRING:
case nsIDataType::VTYPE_CSTRING:
case nsIDataType::VTYPE_ASTRING:
// Nodeset
case nsIDataType::VTYPE_INTERFACE:
case nsIDataType::VTYPE_INTERFACE_IS:
case nsIDataType::VTYPE_ARRAY:
{
// This might still be an error, but we'll only
// find out later since we lazily evaluate.
break;
}
default:
{
return NS_ERROR_FAILURE;
}
}
nsresult rv;
nsCOMPtr<nsINameSpaceManager> namespaceManager =
do_GetService(kNameSpaceManagerCID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 nsId = kNameSpaceID_Unknown;
rv = namespaceManager->RegisterNameSpace(aNamespaceURI, nsId);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIAtom> localName = do_GetAtom(aLocalName);
txExpandedName varName(nsId, localName);
txVariable* var = (txVariable*)mVariables.get(varName);
if (var) {
var->setValue(aValue);
return NS_OK;
}
var = new txVariable(aValue);
NS_ENSURE_TRUE(var, NS_ERROR_OUT_OF_MEMORY);
return mVariables.add(varName, var);
}
NS_IMETHODIMP
txMozillaXSLTProcessor::GetParameter(const nsAString& aNamespaceURI,
const nsAString& aLocalName,
nsIVariant **aResult)
{
nsresult rv;
nsCOMPtr<nsINameSpaceManager> namespaceManager =
do_GetService(kNameSpaceManagerCID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 nsId = kNameSpaceID_Unknown;
rv = namespaceManager->RegisterNameSpace(aNamespaceURI, nsId);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIAtom> localName = do_GetAtom(aLocalName);
txExpandedName varName(nsId, localName);
txVariable* var = (txVariable*)mVariables.get(varName);
if (var) {
return var->getValue(aResult);
}
return NS_OK;
}
NS_IMETHODIMP
txMozillaXSLTProcessor::RemoveParameter(const nsAString& aNamespaceURI,
const nsAString& aLocalName)
{
nsresult rv;
nsCOMPtr<nsINameSpaceManager> namespaceManager =
do_GetService(kNameSpaceManagerCID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 nsId = kNameSpaceID_Unknown;
rv = namespaceManager->RegisterNameSpace(aNamespaceURI, nsId);
nsCOMPtr<nsIAtom> localName = do_GetAtom(aLocalName);
txExpandedName varName(nsId, localName);
mVariables.remove(varName);
return NS_OK;
}
NS_IMETHODIMP
txMozillaXSLTProcessor::ClearParameters()
{
mVariables.clear();
return NS_OK;
}
/* static*/
nsresult
txVariable::Convert(nsIVariant *aValue, ExprResult** aResult)
{
*aResult = nsnull;
PRUint16 dataType;
aValue->GetDataType(&dataType);
switch (dataType) {
// Number
case nsIDataType::VTYPE_INT8:
case nsIDataType::VTYPE_INT16:
case nsIDataType::VTYPE_INT32:
case nsIDataType::VTYPE_INT64:
case nsIDataType::VTYPE_UINT8:
case nsIDataType::VTYPE_UINT16:
case nsIDataType::VTYPE_UINT32:
case nsIDataType::VTYPE_UINT64:
case nsIDataType::VTYPE_FLOAT:
case nsIDataType::VTYPE_DOUBLE:
{
double value;
nsresult rv = aValue->GetAsDouble(&value);
NS_ENSURE_SUCCESS(rv, rv);
*aResult = new NumberResult(value);
NS_ENSURE_TRUE(aResult, NS_ERROR_OUT_OF_MEMORY);
return NS_OK;
}
// Boolean
case nsIDataType::VTYPE_BOOL:
{
PRBool value;
nsresult rv = aValue->GetAsBool(&value);
NS_ENSURE_SUCCESS(rv, rv);
*aResult = new BooleanResult(value);
NS_ENSURE_TRUE(aResult, NS_ERROR_OUT_OF_MEMORY);
return NS_OK;
}
// String
case nsIDataType::VTYPE_CHAR:
case nsIDataType::VTYPE_WCHAR:
case nsIDataType::VTYPE_DOMSTRING:
case nsIDataType::VTYPE_CHAR_STR:
case nsIDataType::VTYPE_WCHAR_STR:
case nsIDataType::VTYPE_STRING_SIZE_IS:
case nsIDataType::VTYPE_WSTRING_SIZE_IS:
case nsIDataType::VTYPE_UTF8STRING:
case nsIDataType::VTYPE_CSTRING:
case nsIDataType::VTYPE_ASTRING:
{
String value;
nsresult rv = aValue->GetAsAString(value);
NS_ENSURE_SUCCESS(rv, rv);
*aResult = new StringResult(value);
NS_ENSURE_TRUE(aResult, NS_ERROR_OUT_OF_MEMORY);
return NS_OK;
}
// Nodeset
case nsIDataType::VTYPE_INTERFACE:
case nsIDataType::VTYPE_INTERFACE_IS:
{
nsID *iid;
nsCOMPtr<nsISupports> supports;
nsresult rv = aValue->GetAsInterface(&iid, getter_AddRefs(supports));
NS_ENSURE_SUCCESS(rv, rv);
if (iid) {
// XXX Figure out what the user added and if we can do
// anything with it.
// nsIDOMNode, nsIDOMNodeList, nsIDOMXPathResult
nsMemory::Free(iid);
}
break;
}
case nsIDataType::VTYPE_ARRAY:
{
// XXX Figure out what the user added and if we can do
// anything with it. Array of Nodes.
break;
}
}
return NS_ERROR_ILLEGAL_VALUE;
}

Просмотреть файл

@ -0,0 +1,147 @@
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Van der Beken <peterv@netscape.com> (original author)
*
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef TRANSFRMX_TXMOZILLAXSLTPROCESSOR_H
#define TRANSFRMX_TXMOZILLAXSLTPROCESSOR_H
#include "ExprResult.h"
#include "nsIDocumentTransformer.h"
#include "nsIVariant.h"
#include "nsIXSLTProcessor.h"
#include "nsVoidArray.h"
#include "nsWeakPtr.h"
#include "txExpandedNameMap.h"
#include "XSLTProcessor.h"
#include "nsIDOMNode.h"
#include "txXMLEventHandler.h"
#include "nsIDOMDocument.h"
#include "nsIDOMDocumentFragment.h"
#include "nsIXSLTProcessorObsolete.h"
/* bacd8ad0-552f-11d3-a9f7-000064657374 */
#define TRANSFORMIIX_XSLT_PROCESSOR_CID \
{ 0xbacd8ad0, 0x552f, 0x11d3, {0xa9, 0xf7, 0x00, 0x00, 0x64, 0x65, 0x73, 0x74} }
#define TRANSFORMIIX_XSLT_PROCESSOR_CONTRACTID \
"@mozilla.org/document-transformer;1?type=text/xsl"
class txVariable : public txIGlobalParameter
{
public:
txVariable(nsIVariant *aValue) : mValue(aValue),
mTxValue(nsnull)
{
}
~txVariable()
{
delete mTxValue;
}
nsresult getValue(ExprResult** aValue)
{
NS_ASSERTION(mValue, "variablevalue is null");
if (!mTxValue) {
nsresult rv = Convert(mValue, &mTxValue);
NS_ENSURE_SUCCESS(rv, rv);
}
*aValue = mTxValue;
return NS_OK;
}
nsresult getValue(nsIVariant** aValue)
{
*aValue = mValue;
NS_ADDREF(*aValue);
return NS_OK;
}
void setValue(nsIVariant* aValue)
{
NS_ASSERTION(aValue, "setting variablevalue to null");
mValue = aValue;
delete mTxValue;
mTxValue = nsnull;
}
private:
static nsresult Convert(nsIVariant *aValue, ExprResult** aResult);
nsCOMPtr<nsIVariant> mValue;
ExprResult* mTxValue;
};
/**
* txMozillaXSLTProcessor is a front-end to the XSLT Processor.
*/
class txMozillaXSLTProcessor : public nsIXSLTProcessor,
public nsIXSLTProcessorObsolete,
public nsIDocumentTransformer
{
public:
/**
* Creates a new txMozillaXSLTProcessor
*/
txMozillaXSLTProcessor();
/**
* Default destructor for txMozillaXSLTProcessor
*/
virtual ~txMozillaXSLTProcessor();
// nsISupports interface
NS_DECL_ISUPPORTS
// nsIXSLTProcessor interface
NS_DECL_NSIXSLTPROCESSOR
// nsIXSLTProcessorObsolete interface
NS_DECL_NSIXSLTPROCESSOROBSOLETE
// nsIDocumentTransformer interface
NS_IMETHOD TransformDocument(nsIDOMNode *aSourceDOM,
nsIDOMNode *aStyleDOM,
nsITransformObserver *aObserver,
nsIDOMDocument **_retval);
protected:
nsCOMPtr<nsIDOMNode> mStylesheet;
txExpandedNameMap mVariables;
};
#endif

Просмотреть файл

@ -0,0 +1,359 @@
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Van der Beken <peterv@netscape.com> (original author)
* Axel Hecht <axel@pike.org>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "txStandaloneXSLTProcessor.h"
#include "txURIUtils.h"
#include "XMLParser.h"
#include "txSingleNodeContext.h"
#include "Names.h"
#include "txUnknownHandler.h"
#include "txHTMLOutput.h"
#include "txTextOutput.h"
/**
* Output Handler Factory
*/
class txStandaloneHandlerFactory : public txIOutputHandlerFactory
{
public:
txStandaloneHandlerFactory(ProcessorState* aPs,
ostream* aStream)
: mPs(aPs), mStream(aStream)
{
}
virtual ~txStandaloneHandlerFactory()
{
};
TX_DECL_TXIOUTPUTHANDLERFACTORY;
private:
ProcessorState* mPs;
ostream* mStream;
};
nsresult
txStandaloneHandlerFactory::createHandlerWith(txOutputFormat* aFormat,
txIOutputXMLEventHandler** aHandler)
{
*aHandler = 0;
switch (aFormat->mMethod) {
case eXMLOutput:
*aHandler = new txXMLOutput(aFormat, mStream);
break;
case eHTMLOutput:
*aHandler = new txHTMLOutput(aFormat, mStream);
break;
case eTextOutput:
*aHandler = new txTextOutput(mStream);
break;
case eMethodNotSet:
*aHandler = new txUnknownHandler(mPs);
break;
}
NS_ENSURE_TRUE(*aHandler, NS_ERROR_OUT_OF_MEMORY);
return NS_OK;
}
nsresult
txStandaloneHandlerFactory::createHandlerWith(txOutputFormat* aFormat,
const String& aName,
PRInt32 aNsID,
txIOutputXMLEventHandler** aHandler)
{
*aHandler = 0;
NS_ASSERTION(aFormat->mMethod != eMethodNotSet,
"How can method not be known when root element is?");
NS_ENSURE_TRUE(aFormat->mMethod != eMethodNotSet, NS_ERROR_UNEXPECTED);
return createHandlerWith(aFormat, aHandler);
}
/**
* txStandaloneXSLTProcessor
*/
/**
* Transform a XML document given by path.
* The stylesheet is retrieved by a processing instruction,
* or an error is returned.
*/
nsresult
txStandaloneXSLTProcessor::transform(String& aXMLPath, ostream& aOut,
ErrorObserver& aErr)
{
Document* xmlDoc = parsePath(aXMLPath, aErr);
if (!xmlDoc) {
return NS_ERROR_FAILURE;
}
// transform
nsresult rv = transform(xmlDoc, aOut, aErr);
delete xmlDoc;
return rv;
}
/**
* Transform a XML document given by path with the given
* stylesheet.
*/
nsresult
txStandaloneXSLTProcessor::transform(String& aXMLPath, String& aXSLPath,
ostream& aOut, ErrorObserver& aErr)
{
Document* xmlDoc = parsePath(aXMLPath, aErr);
if (!xmlDoc) {
return NS_ERROR_FAILURE;
}
Document* xslDoc = parsePath(aXSLPath, aErr);
if (!xslDoc) {
delete xmlDoc;
return NS_ERROR_FAILURE;
}
// transform
nsresult rv = transform(xmlDoc, xslDoc, aOut, aErr);
delete xmlDoc;
delete xslDoc;
return rv;
}
/**
* Transform a XML document.
* The stylesheet is retrieved by a processing instruction,
* or an error is returned.
*/
nsresult
txStandaloneXSLTProcessor::transform(Document* aXMLDoc, ostream& aOut,
ErrorObserver& aErr)
{
if (!aXMLDoc) {
return NS_ERROR_INVALID_POINTER;
}
// get stylesheet path
String stylePath;
getHrefFromStylesheetPI(*aXMLDoc, stylePath);
Document* xslDoc = parsePath(stylePath, aErr);
if (!xslDoc) {
return NS_ERROR_FAILURE;
}
// transform
nsresult rv = transform(aXMLDoc, xslDoc, aOut, aErr);
delete xslDoc;
return rv;
}
/**
* Processes the given XML Document using the given XSL document
* and prints the results to the given ostream argument
*/
nsresult
txStandaloneXSLTProcessor::transform(Document* aSource, Node* aStylesheet,
ostream& aOut, ErrorObserver& aErr)
{
// Create a new ProcessorState
Document* stylesheetDoc = 0;
Element* stylesheetElem = 0;
if (aStylesheet->getNodeType() == Node::DOCUMENT_NODE) {
stylesheetDoc = (Document*)aStylesheet;
}
else {
stylesheetElem = (Element*)aStylesheet;
stylesheetDoc = aStylesheet->getOwnerDocument();
}
ProcessorState ps(aSource, stylesheetDoc);
ps.addErrorObserver(aErr);
txSingleNodeContext evalContext(aSource, &ps);
ps.setEvalContext(&evalContext);
// Index templates and process top level xsl elements
nsresult rv = NS_OK;
if (stylesheetElem) {
rv = processTopLevel(stylesheetElem, 0, &ps);
}
else {
rv = processStylesheet(stylesheetDoc, 0, &ps);
}
if (NS_FAILED(rv)) {
return rv;
}
txStandaloneHandlerFactory handlerFactory(&ps, &aOut);
ps.mOutputHandlerFactory = &handlerFactory;
#ifndef XP_WIN
bool sync = aOut.sync_with_stdio(false);
#endif
// Process root of XML source document
txXSLTProcessor::transform(&ps);
#ifndef XP_WIN
aOut.sync_with_stdio(sync);
#endif
return NS_OK;
}
/**
* Parses all XML Stylesheet PIs associated with the
* given XML document. If any stylesheet PIs are found with
* type="text/xsl" the href psuedo attribute value will be
* added to the given href argument. If multiple text/xsl stylesheet PIs
* are found, the one closest to the end of the document is used.
*/
void txStandaloneXSLTProcessor::getHrefFromStylesheetPI(Document& xmlDocument,
String& href)
{
Node* node = xmlDocument.getFirstChild();
String type;
String tmpHref;
while (node) {
if (node->getNodeType() == Node::PROCESSING_INSTRUCTION_NODE) {
String target = ((ProcessingInstruction*)node)->getTarget();
if (STYLESHEET_PI.isEqual(target) ||
STYLESHEET_PI_OLD.isEqual(target)) {
String data = ((ProcessingInstruction*)node)->getData();
type.clear();
tmpHref.clear();
parseStylesheetPI(data, type, tmpHref);
if (XSL_MIME_TYPE.isEqual(type)) {
href.clear();
URIUtils::resolveHref(tmpHref, node->getBaseURI(), href);
}
}
}
node = node->getNextSibling();
}
}
/**
* Parses the contents of data, and returns the type and href pseudo attributes
*/
void txStandaloneXSLTProcessor::parseStylesheetPI(String& data,
String& type,
String& href)
{
PRUint32 size = data.length();
NamedMap bufferMap;
bufferMap.put(String("type"), &type);
bufferMap.put(String("href"), &href);
PRUint32 ccount = 0;
MBool inLiteral = MB_FALSE;
char matchQuote = '"';
String sink;
String* buffer = &sink;
for (ccount = 0; ccount < size; ccount++) {
char ch = data.charAt(ccount);
switch ( ch ) {
case ' ':
if (inLiteral) {
buffer->append(ch);
}
break;
case '=':
if (inLiteral) {
buffer->append(ch);
}
else if (buffer->length() > 0) {
buffer = (String*)bufferMap.get(*buffer);
if (!buffer) {
sink.clear();
buffer = &sink;
}
}
break;
case '"':
case '\'':
if (inLiteral) {
if (matchQuote == ch) {
inLiteral = MB_FALSE;
sink.clear();
buffer = &sink;
}
else {
buffer->append(ch);
}
}
else {
inLiteral = MB_TRUE;
matchQuote = ch;
}
break;
default:
buffer->append(ch);
break;
}
}
}
Document*
txStandaloneXSLTProcessor::parsePath(const String& aPath, ErrorObserver& aErr)
{
ifstream xmlInput(NS_LossyConvertUCS2toASCII(aPath).get(), ios::in);
if (!xmlInput) {
String err("Couldn't open ");
err.append(aPath);
aErr.receiveError(err);
return 0;
}
// parse source
XMLParser xmlParser;
Document* xmlDoc = xmlParser.parse(xmlInput, aPath);
if (!xmlDoc) {
String err("Parsing error in ");
err.append(aPath);
aErr.receiveError(err);
}
return xmlDoc;
}

Просмотреть файл

@ -0,0 +1,162 @@
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Van der Beken <peterv@netscape.com> (original author)
* Axel Hecht <axel@pike.org>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef TRANSFRMX_TXSTANDALONEXSLTPROCESSOR_H
#define TRANSFRMX_TXSTANDALONEXSLTPROCESSOR_H
#include "XSLTProcessor.h"
#ifndef __BORLANDC__
#include <iostream.h>
#include <fstream.h>
#endif
class txStreamXMLEventHandler;
/**
* txStandaloneXSLTProcessor
*
* Use of the standalone TransforMiiX API:
*
* The XSLT Processor need initialisation and shutdown
* by
* txStandaloneXSLTProcessor::Init();
* and
* txStandaloneXSLTProcessor::Shutdown();
* Be sure to always call these functions in pairs.
*
* The API to transform documents consists of entry points
* to transform either one or two documents.
* If you provide one document, the stylesheet location is
* computed from the processing instruction. If that cannot
* be found, an error is issued.
*
* The result is output to a stream.
*
* Documents can be provided either by path or by DOM Document.
*
* Stylesheet parameters
* XXX TODO
*
*/
class txStandaloneXSLTProcessor : public txXSLTProcessor
{
public:
/**
* Methods that print the result to a stream
*/
/**
* Transform a XML document given by path.
* The stylesheet is retrieved by a processing instruction,
* or an error is returned.
*
* @param aXMLPath path to the source document
* @param aOut stream to which the result is feeded
* @param aErr error observer
* @result NS_OK if transformation was successful
*/
nsresult transform(String& aXMLPath, ostream& aOut, ErrorObserver& aErr);
/**
* Transform a XML document given by path with the given
* stylesheet.
*
* @param aXMLPath path to the source document
* @param aXSLPath path to the style document
* @param aOut stream to which the result is feeded
* @param aErr error observer
* @result NS_OK if transformation was successful
*/
nsresult transform(String& aXMLPath, String& aXSLPath, ostream& aOut,
ErrorObserver& aErr);
/**
* Transform a XML document.
* The stylesheet is retrieved by a processing instruction,
* or an error is returned.
*
* @param aXMLDoc source document
* @param aOut stream to which the result is feeded
* @param aErr error observer
* @result NS_OK if transformation was successful
*/
nsresult transform(Document* aXMLDoc, ostream& aOut, ErrorObserver& aErr);
/**
* Transform a XML document with the given stylesheet.
*
* @param aXMLDoc source document
* @param aXSLNode style node
* @param aOut stream to which the result is feeded
* @param aErr error observer
* @result NS_OK if transformation was successful
*/
nsresult transform(Document* aXMLDoc, Node* aXSLNode,
ostream& aOut, ErrorObserver& aErr);
protected:
/**
* Parses all XML Stylesheet PIs associated with the
* given XML document. If any stylesheet PIs are found with
* type="text/xsl" the href psuedo attribute value will be
* added to the given href argument. If multiple text/xsl stylesheet PIs
* are found, the one closest to the end of the document is used.
*/
static void getHrefFromStylesheetPI(Document& xmlDocument, String& href);
/**
* Parses the contents of data, returns the type and href psuedo attributes
*/
static void parseStylesheetPI(String& data,
String& type,
String& href);
/**
* Create a Document from a path.
*
* @param aPath path to the xml file
* @param aErr ErrorObserver
* @result Document XML Document, or null on error
*/
static Document* parsePath(const String& aPath, ErrorObserver& aErr);
};
#endif

Просмотреть файл

@ -39,7 +39,8 @@
#include "txTextOutput.h" #include "txTextOutput.h"
#include "TxString.h" #include "TxString.h"
txTextOutput::txTextOutput() txTextOutput::txTextOutput(ostream* aOut)
: mOut(aOut)
{ {
} }
@ -89,21 +90,3 @@ void txTextOutput::startElement(const String& aName,
const PRInt32 aNsID) const PRInt32 aNsID)
{ {
} }
void txTextOutput::getOutputStream(ostream** aOutputStream)
{
if (aOutputStream)
*aOutputStream = mOut;
}
void txTextOutput::setOutputStream(ostream* aOutputStream)
{
mOut = aOutputStream;
}
void txTextOutput::setOutputFormat(txOutputFormat* aOutputFormat)
{
mOutputFormat.reset();
mOutputFormat.merge(*aOutputFormat);
mOutputFormat.setFromDefaults();
}

Просмотреть файл

@ -42,10 +42,10 @@
#include "txXMLEventHandler.h" #include "txXMLEventHandler.h"
#include "txOutputFormat.h" #include "txOutputFormat.h"
class txTextOutput : public txStreamXMLEventHandler class txTextOutput : public txIOutputXMLEventHandler
{ {
public: public:
txTextOutput(); txTextOutput(ostream* aOut);
~txTextOutput(); ~txTextOutput();
/* /*
@ -95,6 +95,18 @@ public:
void endElement(const String& aName, void endElement(const String& aName,
const PRInt32 aNsID); const PRInt32 aNsID);
/**
* Returns whether the output handler supports
* disable-output-escaping.
*
* @return MB_TRUE if this handler supports
* disable-output-escaping
*/
MBool hasDisableOutputEscaping()
{
return MB_TRUE;
}
/* /*
* Signals to receive a processing instruction. * Signals to receive a processing instruction.
* *
@ -118,30 +130,8 @@ public:
void startElement(const String& aName, void startElement(const String& aName,
const PRInt32 aNsID); const PRInt32 aNsID);
/*
* Sets the output format.
*
* @param aOutputFormat the output format
*/
void setOutputFormat(txOutputFormat* aOutputFormat);
/**
* Get the output stream.
*
* @param aOutputStream the current output stream
*/
void getOutputStream(ostream** aOutputStream);
/**
* Sets the output stream.
*
* @param aDocument the Mozilla output document
*/
void setOutputStream(ostream* aOutputStream);
private: private:
ostream* mOut; ostream* mOut;
txOutputFormat mOutputFormat;
}; };
#endif #endif

Просмотреть файл

@ -38,12 +38,22 @@
#include "txUnknownHandler.h" #include "txUnknownHandler.h"
#include <string.h> #include <string.h>
#include "ProcessorState.h"
#ifndef TX_EXE
NS_IMPL_ISUPPORTS1(txUnknownHandler, txIOutputXMLEventHandler);
#endif
PRUint32 txUnknownHandler::kReasonableTransactions = 8; PRUint32 txUnknownHandler::kReasonableTransactions = 8;
txUnknownHandler::txUnknownHandler() : mTotal(0), txUnknownHandler::txUnknownHandler(ProcessorState* aPs)
mMax(kReasonableTransactions) : mTotal(0), mMax(kReasonableTransactions),
mPs(aPs)
{ {
#ifndef TX_EXE
NS_INIT_ISUPPORTS();
#endif
mArray = new txOutputTransaction*[kReasonableTransactions]; mArray = new txOutputTransaction*[kReasonableTransactions];
} }
@ -60,7 +70,9 @@ void txUnknownHandler::attribute(const String& aName,
const PRInt32 aNsID, const PRInt32 aNsID,
const String& aValue) const String& aValue)
{ {
NS_ASSERTION(0, "This shouldn't be called") // If this is called then the stylesheet is trying to add an attribute
// without adding an element first. So we'll just ignore it.
// XXX ErrorReport: Signal this?
} }
void txUnknownHandler::characters(const String& aData) void txUnknownHandler::characters(const String& aData)
@ -69,7 +81,7 @@ void txUnknownHandler::characters(const String& aData)
new txOneStringTransaction(txOutputTransaction::eCharacterTransaction, new txOneStringTransaction(txOutputTransaction::eCharacterTransaction,
aData); aData);
if (!transaction) { if (!transaction) {
NS_ASSERTION(0, "Out of memory!") NS_ASSERTION(0, "Out of memory!");
return; return;
} }
addTransaction(transaction); addTransaction(transaction);
@ -81,7 +93,7 @@ void txUnknownHandler::charactersNoOutputEscaping(const String& aData)
new txOneStringTransaction(txOutputTransaction::eCharacterNoOETransaction, new txOneStringTransaction(txOutputTransaction::eCharacterNoOETransaction,
aData); aData);
if (!transaction) { if (!transaction) {
NS_ASSERTION(0, "Out of memory!") NS_ASSERTION(0, "Out of memory!");
return; return;
} }
addTransaction(transaction); addTransaction(transaction);
@ -93,7 +105,7 @@ void txUnknownHandler::comment(const String& aData)
new txOneStringTransaction(txOutputTransaction::eCommentTransaction, new txOneStringTransaction(txOutputTransaction::eCommentTransaction,
aData); aData);
if (!transaction) { if (!transaction) {
NS_ASSERTION(0, "Out of memory!") NS_ASSERTION(0, "Out of memory!");
return; return;
} }
addTransaction(transaction); addTransaction(transaction);
@ -101,19 +113,32 @@ void txUnknownHandler::comment(const String& aData)
void txUnknownHandler::endDocument() void txUnknownHandler::endDocument()
{ {
txOutputTransaction* transaction = // This is an unusual case, no output method has been set and we
new txOutputTransaction(txOutputTransaction::eEndDocumentTransaction); // didn't create a document element. Switching to XML output mode
if (!transaction) { // anyway.
NS_ASSERTION(0, "Out of memory!")
#ifndef TX_EXE
// Make sure that we don't get deleted while this function is executed and
// we set a new outputhandler
nsCOMPtr<txIOutputXMLEventHandler> kungFuDeathGrip(this);
#endif
nsresult rv = createHandlerAndFlush(eXMLOutput, String(),
kNameSpaceID_None);
if (NS_FAILED(rv))
return; return;
}
addTransaction(transaction); mPs->mResultHandler->endDocument();
// in module the outputhandler is refcounted
#ifdef TX_EXE
delete this;
#endif
} }
void txUnknownHandler::endElement(const String& aName, void txUnknownHandler::endElement(const String& aName,
const PRInt32 aNsID) const PRInt32 aNsID)
{ {
NS_ASSERTION(0, "This shouldn't be called") NS_ASSERTION(0, "This shouldn't be called");
} }
void txUnknownHandler::processingInstruction(const String& aTarget, void txUnknownHandler::processingInstruction(const String& aTarget,
@ -123,7 +148,7 @@ void txUnknownHandler::processingInstruction(const String& aTarget,
new txTwoStringTransaction(txOutputTransaction::ePITransaction, new txTwoStringTransaction(txOutputTransaction::ePITransaction,
aTarget, aData); aTarget, aData);
if (!transaction) { if (!transaction) {
NS_ASSERTION(0, "Out of memory!") NS_ASSERTION(0, "Out of memory!");
return; return;
} }
addTransaction(transaction); addTransaction(transaction);
@ -134,7 +159,7 @@ void txUnknownHandler::startDocument()
txOutputTransaction* transaction = txOutputTransaction* transaction =
new txOutputTransaction(txOutputTransaction::eStartDocumentTransaction); new txOutputTransaction(txOutputTransaction::eStartDocumentTransaction);
if (!transaction) { if (!transaction) {
NS_ASSERTION(0, "Out of memory!") NS_ASSERTION(0, "Out of memory!");
return; return;
} }
addTransaction(transaction); addTransaction(transaction);
@ -143,74 +168,108 @@ void txUnknownHandler::startDocument()
void txUnknownHandler::startElement(const String& aName, void txUnknownHandler::startElement(const String& aName,
const PRInt32 aNsID) const PRInt32 aNsID)
{ {
NS_ASSERTION(0, "This shouldn't be called") #ifndef TX_EXE
} // Make sure that we don't get deleted while this function is executed and
// we set a new outputhandler
nsCOMPtr<txIOutputXMLEventHandler> kungFuDeathGrip(this);
#endif
void txUnknownHandler::setOutputFormat(txOutputFormat* aOutputFormat) nsresult rv = NS_OK;
{ txOutputFormat* format = mPs->getOutputFormat();
} if (format->mMethod != eMethodNotSet) {
rv = createHandlerAndFlush(format->mMethod, aName, aNsID);
void txUnknownHandler::getOutputStream(ostream** aOutputStream)
{
if (aOutputStream) {
*aOutputStream = mOut;
} }
else if (aNsID == kNameSpaceID_None &&
aName.isEqualIgnoreCase(String("html"))) {
rv = createHandlerAndFlush(eHTMLOutput, aName, aNsID);
}
else {
rv = createHandlerAndFlush(eXMLOutput, aName, aNsID);
}
if (NS_FAILED(rv))
return;
mPs->mResultHandler->startElement(aName, aNsID);
// in module the outputhandler is refcounted
#ifdef TX_EXE
delete this;
#endif
} }
void txUnknownHandler::setOutputStream(ostream* aOutputStream) #ifndef TX_EXE
void txUnknownHandler::getOutputDocument(nsIDOMDocument** aDocument)
{ {
mOut = aOutputStream; *aDocument = nsnull;
} }
#endif
void txUnknownHandler::flush(txStreamXMLEventHandler* aHandler) nsresult txUnknownHandler::createHandlerAndFlush(txOutputMethod aMethod,
const String& aName,
const PRInt32 aNsID)
{ {
nsresult rv = NS_OK;
txOutputFormat* format = mPs->getOutputFormat();
format->mMethod = aMethod;
txIOutputXMLEventHandler* handler = 0;
rv = mPs->mOutputHandlerFactory->createHandlerWith(format, aName, aNsID,
&handler);
NS_ENSURE_SUCCESS(rv, rv);
mPs->mOutputHandler = handler;
mPs->mResultHandler = handler;
MBool hasDOE = handler->hasDisableOutputEscaping();
PRUint32 counter; PRUint32 counter;
for (counter = 0; counter < mTotal; ++counter) { for (counter = 0; counter < mTotal; ++counter) {
switch (mArray[counter]->mType) { switch (mArray[counter]->mType) {
case txOutputTransaction::eCharacterTransaction: case txOutputTransaction::eCharacterTransaction:
{ {
txOneStringTransaction* transaction = (txOneStringTransaction*)mArray[counter]; txOneStringTransaction* transaction = (txOneStringTransaction*)mArray[counter];
aHandler->characters(transaction->mString); handler->characters(transaction->mString);
delete transaction; delete transaction;
break; break;
} }
case txOutputTransaction::eCharacterNoOETransaction: case txOutputTransaction::eCharacterNoOETransaction:
{ {
txOneStringTransaction* transaction = (txOneStringTransaction*)mArray[counter]; txOneStringTransaction* transaction = (txOneStringTransaction*)mArray[counter];
aHandler->charactersNoOutputEscaping(transaction->mString); if (hasDOE) {
handler->charactersNoOutputEscaping(transaction->mString);
}
else {
handler->characters(transaction->mString);
}
delete transaction; delete transaction;
break; break;
} }
case txOutputTransaction::eCommentTransaction: case txOutputTransaction::eCommentTransaction:
{ {
txOneStringTransaction* transaction = (txOneStringTransaction*)mArray[counter]; txOneStringTransaction* transaction = (txOneStringTransaction*)mArray[counter];
aHandler->comment(transaction->mString); handler->comment(transaction->mString);
delete transaction; delete transaction;
break; break;
} }
case txOutputTransaction::eEndDocumentTransaction:
{
aHandler->endDocument();
delete mArray[counter];
break;
}
case txOutputTransaction::ePITransaction: case txOutputTransaction::ePITransaction:
{ {
txTwoStringTransaction* transaction = (txTwoStringTransaction*)mArray[counter]; txTwoStringTransaction* transaction = (txTwoStringTransaction*)mArray[counter];
aHandler->processingInstruction(transaction->mStringOne, handler->processingInstruction(transaction->mStringOne,
transaction->mStringTwo); transaction->mStringTwo);
delete transaction; delete transaction;
break; break;
} }
case txOutputTransaction::eStartDocumentTransaction: case txOutputTransaction::eStartDocumentTransaction:
{ {
aHandler->startDocument(); handler->startDocument();
delete mArray[counter]; delete mArray[counter];
break; break;
} }
} }
} }
mTotal = 0; mTotal = 0;
return NS_OK;
} }
void txUnknownHandler::addTransaction(txOutputTransaction* aTransaction) void txUnknownHandler::addTransaction(txOutputTransaction* aTransaction)
@ -219,7 +278,7 @@ void txUnknownHandler::addTransaction(txOutputTransaction* aTransaction)
PRUint32 newMax = mMax * 2; PRUint32 newMax = mMax * 2;
txOutputTransaction** newArray = new txOutputTransaction*[newMax]; txOutputTransaction** newArray = new txOutputTransaction*[newMax];
if (!newArray) { if (!newArray) {
NS_ASSERTION(0, "Out of memory!") NS_ASSERTION(0, "Out of memory!");
return; return;
} }
mMax = newMax; mMax = newMax;

Просмотреть файл

@ -41,6 +41,9 @@
#include "txXMLEventHandler.h" #include "txXMLEventHandler.h"
#include "TxString.h" #include "TxString.h"
#include "txOutputFormat.h"
class ProcessorState;
class txOutputTransaction class txOutputTransaction
{ {
@ -49,7 +52,6 @@ public:
eCharacterTransaction, eCharacterTransaction,
eCharacterNoOETransaction, eCharacterNoOETransaction,
eCommentTransaction, eCommentTransaction,
eEndDocumentTransaction,
ePITransaction, ePITransaction,
eStartDocumentTransaction eStartDocumentTransaction
}; };
@ -90,12 +92,16 @@ public:
String mStringTwo; String mStringTwo;
}; };
class txUnknownHandler : public txStreamXMLEventHandler class txUnknownHandler : public txIOutputXMLEventHandler
{ {
public: public:
txUnknownHandler(); txUnknownHandler(ProcessorState* aPs);
virtual ~txUnknownHandler(); virtual ~txUnknownHandler();
#ifndef TX_EXE
NS_DECL_ISUPPORTS
#endif
/* /*
* Signals to receive the start of an attribute. * Signals to receive the start of an attribute.
* *
@ -143,6 +149,18 @@ public:
void endElement(const String& aName, void endElement(const String& aName,
const PRInt32 aNsID); const PRInt32 aNsID);
/**
* Returns whether the output handler supports
* disable-output-escaping.
*
* @return MB_TRUE if this handler supports
* disable-output-escaping
*/
MBool hasDisableOutputEscaping()
{
return MB_TRUE;
}
/* /*
* Signals to receive a processing instruction. * Signals to receive a processing instruction.
* *
@ -165,34 +183,29 @@ public:
*/ */
void startElement(const String& aName, void startElement(const String& aName,
const PRInt32 aNsID); const PRInt32 aNsID);
/*
* Sets the output format.
*
* @param aOutputFormat the output format
*/
void setOutputFormat(txOutputFormat* aOutputFormat);
#ifndef TX_EXE
/** /**
* Get the output stream. * Gets the Mozilla output document
* *
* @param aOutputStream the current output stream * @param aDocument the Mozilla output document
*/ */
void getOutputStream(ostream** aOutputStream); void getOutputDocument(nsIDOMDocument** aDocument);
#endif
/*
* Sets the output stream.
*
* @param aOutputStream the output stream
*/
void setOutputStream(ostream* aOutputStream);
void flush(txStreamXMLEventHandler* aHandler);
private: private:
nsresult createHandlerAndFlush(txOutputMethod aMethod,
const String& aName,
const PRInt32 aNsID);
void addTransaction(txOutputTransaction* aTransaction); void addTransaction(txOutputTransaction* aTransaction);
PRUint32 mTotal, mMax; PRUint32 mTotal, mMax;
ostream* mOut; /*
* XXX we shouldn't hold to the ProcessorState, as we're supposed
* to live without it. But as a standalone handler, we don't.
* The right fix may need a txOutputFormat here.
*/
ProcessorState* mPs;
txOutputTransaction** mArray; txOutputTransaction** mArray;
static PRUint32 kReasonableTransactions; static PRUint32 kReasonableTransactions;

Просмотреть файл

@ -25,14 +25,20 @@
#define TRANSFRMX_XML_EVENT_HANDLER_H #define TRANSFRMX_XML_EVENT_HANDLER_H
#include "baseutils.h" #include "baseutils.h"
#include "txError.h"
class String; class String;
class txOutputFormat; class txOutputFormat;
#ifdef TX_EXE #ifdef TX_EXE
#include <iostream.h> #include <iostream.h>
#else #else
#include "nsISupports.h"
#define kTXNameSpaceURI "http://www.mozilla.org/TransforMiix"
#define kTXWrapper "transformiix:result"
class nsIContent; class nsIContent;
class nsIDOMDocument; class nsIDOMDocument;
class nsIDOMHTMLScriptElement; class nsIDOMHTMLScriptElement;
class nsITransformObserver;
#endif #endif
/** /**
@ -109,79 +115,84 @@ public:
const PRInt32 aNsID) = 0; const PRInt32 aNsID) = 0;
}; };
class txOutputXMLEventHandler : public txXMLEventHandler
{
public:
/**
* Sets the output format.
*
* @param aOutputFormat the output format
*/
virtual void setOutputFormat(txOutputFormat* aOutputFormat) = 0;
};
#ifdef TX_EXE #ifdef TX_EXE
class txStreamXMLEventHandler : public txOutputXMLEventHandler class txIOutputXMLEventHandler : public txXMLEventHandler
#else
#define TX_IOUTPUTXMLEVENTHANDLER_IID \
{ 0x80e5e802, 0x8c88, 0x11d6, \
{ 0xa7, 0xf2, 0xc5, 0xc3, 0x85, 0x6b, 0xbb, 0xbc }}
class txIOutputXMLEventHandler : public nsISupports,
public txXMLEventHandler
#endif
{ {
public: public:
/**
* Get the output stream.
*
* @param aOutputStream the current output stream
*/
virtual void getOutputStream(ostream** aOutputStream) = 0;
/**
* Sets the output stream.
*
* @param aOutputStream the output stream
*/
virtual void setOutputStream(ostream* aOutputStream) = 0;
/** /**
* Signals to receive characters that don't need output escaping. * Signals to receive characters that don't need output escaping.
* *
* @param aData the characters to receive * @param aData the characters to receive
*/ */
virtual void charactersNoOutputEscaping(const String& aData) = 0; virtual void charactersNoOutputEscaping(const String& aData) = 0;
};
#else
class txMozillaXMLEventHandler : public txOutputXMLEventHandler
{
public:
/**
* Disables loading of stylesheets.
*/
virtual void disableStylesheetLoad() = 0;
/** /**
* Returns the root content of the result. * Returns whether the output handler supports
* disable-output-escaping.
* *
* @param aReturn the root content * @return MB_TRUE if this handler supports
* disable-output-escaping
*/ */
virtual nsresult getRootContent(nsIContent** aReturn) = 0; virtual MBool hasDisableOutputEscaping() = 0;
#ifndef TX_EXE
NS_DEFINE_STATIC_IID_ACCESSOR(TX_IOUTPUTXMLEVENTHANDLER_IID)
/** /**
* Returns PR_TRUE if the event handler has finished anything * Gets the Mozilla output document
* extra that had to happen after the transform has finished.
*/
virtual PRBool isDone() = 0;
/**
* Removes a script element from the array of elements that are
* still loading.
*
* @param aReturn the script element to remove
*/
virtual void removeScriptElement(nsIDOMHTMLScriptElement *aElement) = 0;
/**
* Sets the Mozilla output document.
* *
* @param aDocument the Mozilla output document * @param aDocument the Mozilla output document
*/ */
virtual void setOutputDocument(nsIDOMDocument* aDocument) = 0; virtual void getOutputDocument(nsIDOMDocument** aDocument) = 0;
};
#endif #endif
};
/**
* Interface used to create the appropriate outputhandler
*/
class txIOutputHandlerFactory
{
public:
virtual ~txIOutputHandlerFactory() {};
/**
* Creates an outputhandler for the specified format.
* @param aFromat format to get handler for
* @param aHandler outparam. The created handler
*/
virtual nsresult
createHandlerWith(txOutputFormat* aFormat,
txIOutputXMLEventHandler** aHandler) = 0;
/**
* Creates an outputhandler for the specified format, with the specified
* name and namespace for the root element.
* @param aFromat format to get handler for
* @param aName name of the root element
* @param aNsID namespace-id of the root element
* @param aHandler outparam. The created handler
*/
virtual nsresult
createHandlerWith(txOutputFormat* aFormat,
const String& aName,
PRInt32 aNsID,
txIOutputXMLEventHandler** aHandler) = 0;
};
#define TX_DECL_TXIOUTPUTHANDLERFACTORY \
nsresult createHandlerWith(txOutputFormat* aFormat, \
txIOutputXMLEventHandler** aHandler); \
nsresult createHandlerWith(txOutputFormat* aFormat, \
const String& aName, \
PRInt32 aNsID, \
txIOutputXMLEventHandler** aHandler) \
#endif #endif

Просмотреть файл

@ -47,13 +47,17 @@ txAttribute::txAttribute(PRInt32 aNsID, txAtom* aLocalName, const String& aValue
{ {
} }
txXMLOutput::txXMLOutput() : mUseEmptyElementShorthand(MB_TRUE), txXMLOutput::txXMLOutput(txOutputFormat* aFormat, ostream* aOut)
mHaveDocumentElement(MB_FALSE), : mOut(aOut),
mStartTagOpen(MB_FALSE), mUseEmptyElementShorthand(MB_TRUE),
mAfterEndTag(MB_FALSE), mHaveDocumentElement(MB_FALSE),
mInCDATASection(MB_FALSE), mStartTagOpen(MB_FALSE),
mIndentLevel(0) mAfterEndTag(MB_FALSE),
mInCDATASection(MB_FALSE),
mIndentLevel(0)
{ {
mOutputFormat.merge(*aFormat);
mOutputFormat.setFromDefaults();
} }
txXMLOutput::~txXMLOutput() txXMLOutput::~txXMLOutput()
@ -251,24 +255,6 @@ void txXMLOutput::startElement(const String& aName,
} }
} }
void txXMLOutput::getOutputStream(ostream** aOutputStream)
{
if (aOutputStream)
*aOutputStream = mOut;
}
void txXMLOutput::setOutputStream(ostream* aOutputStream)
{
mOut = aOutputStream;
}
void txXMLOutput::setOutputFormat(txOutputFormat* aOutputFormat)
{
mOutputFormat.reset();
mOutputFormat.merge(*aOutputFormat);
mOutputFormat.setFromDefaults();
}
void txXMLOutput::closeStartTag(MBool aUseEmptyElementShorthand) void txXMLOutput::closeStartTag(MBool aUseEmptyElementShorthand)
{ {
mAfterEndTag = aUseEmptyElementShorthand; mAfterEndTag = aUseEmptyElementShorthand;

Просмотреть файл

@ -91,10 +91,10 @@ public:
MBool mShorthand; MBool mShorthand;
}; };
class txXMLOutput : public txStreamXMLEventHandler class txXMLOutput : public txIOutputXMLEventHandler
{ {
public: public:
txXMLOutput(); txXMLOutput(txOutputFormat* aFormat, ostream* aOut);
virtual ~txXMLOutput(); virtual ~txXMLOutput();
static const int DEFAULT_INDENT; static const int DEFAULT_INDENT;
@ -146,6 +146,18 @@ public:
virtual void endElement(const String& aName, virtual void endElement(const String& aName,
const PRInt32 aNsID); const PRInt32 aNsID);
/**
* Returns whether the output handler supports
* disable-output-escaping.
*
* @return MB_TRUE if this handler supports
* disable-output-escaping
*/
MBool hasDisableOutputEscaping()
{
return MB_TRUE;
}
/* /*
* Signals to receive a processing instruction. * Signals to receive a processing instruction.
* *
@ -169,27 +181,6 @@ public:
virtual void startElement(const String& aName, virtual void startElement(const String& aName,
const PRInt32 aNsID); const PRInt32 aNsID);
/*
* Sets the output format.
*
* @param aOutputFormat the output format
*/
void setOutputFormat(txOutputFormat* aOutputFormat);
/**
* Get the output stream.
*
* @param aOutputStream the current output stream
*/
void getOutputStream(ostream** aOutputStream);
/**
* Sets the output stream.
*
* @param aOutputStream the new output stream
*/
void setOutputStream(ostream* aOutputStream);
protected: protected:
virtual void closeStartTag(MBool aUseEmptyElementShorthand); virtual void closeStartTag(MBool aUseEmptyElementShorthand);
void printUTF8Char(DOM_CHAR& ch); void printUTF8Char(DOM_CHAR& ch);