diff --git a/mozilla/content/macbuild/contentIDL.xml b/mozilla/content/macbuild/contentIDL.xml index 628322f8d15..8ae04b9777f 100644 --- a/mozilla/content/macbuild/contentIDL.xml +++ b/mozilla/content/macbuild/contentIDL.xml @@ -813,13 +813,6 @@ Text - - Name - nsIDocumentTransformer.idl - MacOS - Text - - Name nsIController.idl @@ -899,14 +892,28 @@ Name - nsITransformObserver.idl + nsISyncLoadDOMService.idl MacOS Text Name - nsISyncLoadDOMService.idl + nsIXSLTException.idl + MacOS + Text + + + + Name + nsIXSLTProcessor.idl + MacOS + Text + + + + Name + nsIXSLTProcessorObsolete.idl MacOS Text @@ -958,11 +965,6 @@ nsISelectionListener.idl MacOS - - Name - nsIDocumentTransformer.idl - MacOS - Name nsIController.idl @@ -1020,12 +1022,22 @@ Name - nsITransformObserver.idl + nsISyncLoadDOMService.idl MacOS Name - nsISyncLoadDOMService.idl + nsIXSLTException.idl + MacOS + + + Name + nsIXSLTProcessor.idl + MacOS + + + Name + nsIXSLTProcessorObsolete.idl MacOS @@ -1790,13 +1802,6 @@ Text - - Name - nsIDocumentTransformer.idl - MacOS - Text - - Name nsIController.idl @@ -1876,14 +1881,28 @@ Name - nsITransformObserver.idl + nsISyncLoadDOMService.idl MacOS Text Name - nsISyncLoadDOMService.idl + nsIXSLTException.idl + MacOS + Text + + + + Name + nsIXSLTProcessor.idl + MacOS + Text + + + + Name + nsIXSLTProcessorObsolete.idl MacOS Text @@ -1935,11 +1954,6 @@ nsISelectionListener.idl MacOS - - Name - nsIDocumentTransformer.idl - MacOS - Name nsIController.idl @@ -1997,12 +2011,22 @@ Name - nsITransformObserver.idl + nsISyncLoadDOMService.idl MacOS Name - nsISyncLoadDOMService.idl + nsIXSLTException.idl + MacOS + + + Name + nsIXSLTProcessor.idl + MacOS + + + Name + nsIXSLTProcessorObsolete.idl MacOS @@ -2069,12 +2093,6 @@ nsISelectionListener.idl MacOS - - headers - Name - nsIDocumentTransformer.idl - MacOS - headers Name @@ -2144,13 +2162,25 @@ headers Name - nsITransformObserver.idl + nsISyncLoadDOMService.idl MacOS headers Name - nsISyncLoadDOMService.idl + nsIXSLTException.idl + MacOS + + + headers + Name + nsIXSLTProcessor.idl + MacOS + + + headers + Name + nsIXSLTProcessorObsolete.idl MacOS diff --git a/mozilla/content/xml/document/resources/XMLPrettyPrint.xml b/mozilla/content/xml/document/resources/XMLPrettyPrint.xml index b092e55e771..7402e6bc393 100644 --- a/mozilla/content/xml/document/resources/XMLPrettyPrint.xml +++ b/mozilla/content/xml/document/resources/XMLPrettyPrint.xml @@ -52,7 +52,7 @@ if (aTopic == "prettyprint-dom-created") - document.getAnonymousNodes(this).item(0).appendChild(aSubject.documentElement); + document.getAnonymousNodes(this).item(0).appendChild(aSubject); diff --git a/mozilla/content/xml/document/resources/XMLPrettyPrint.xsl b/mozilla/content/xml/document/resources/XMLPrettyPrint.xsl index 605c8230f48..99bddf54dfa 100644 --- a/mozilla/content/xml/document/resources/XMLPrettyPrint.xsl +++ b/mozilla/content/xml/document/resources/XMLPrettyPrint.xsl @@ -43,16 +43,14 @@ -
- - - + + + diff --git a/mozilla/content/xml/document/src/nsXMLContentSink.cpp b/mozilla/content/xml/document/src/nsXMLContentSink.cpp index 0d249d30134..fab6f87c5f8 100644 --- a/mozilla/content/xml/document/src/nsXMLContentSink.cpp +++ b/mozilla/content/xml/document/src/nsXMLContentSink.cpp @@ -118,6 +118,7 @@ #include "nsIObserver.h" #include "nsIDocumentTransformer.h" #include "nsISyncLoadDOMService.h" +#include "nsIXSLTProcessor.h" // XXX misnamed header file, but oh well #include "nsHTMLTokens.h" @@ -442,18 +443,17 @@ nsXMLContentSink::MaybePrettyPrint() NS_ENSURE_SUCCESS(rv, rv); // Transform the document - nsCOMPtr transformer = + nsCOMPtr transformer = do_CreateInstance("@mozilla.org/document-transformer;1?type=text/xsl", &rv); NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr resultDocument; - nsAutoString emptyStr; - rv = NS_NewDOMDocument(getter_AddRefs(resultDocument), emptyStr, emptyStr, - nsnull, mDocumentURL); - NS_ENSURE_SUCCESS(rv, rv); + rv = transformer->ImportStylesheet(xslDocument); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr resultFragment; nsCOMPtr sourceDocument = do_QueryInterface(mDocument); - rv = transformer->TransformDocument(sourceDocument, xslDocument, - resultDocument, nsnull); + rv = transformer->TransformToFragment(sourceDocument, xslDocument, + getter_AddRefs(resultFragment)); NS_ENSURE_SUCCESS(rv, rv); // Add the binding @@ -478,7 +478,7 @@ nsXMLContentSink::MaybePrettyPrint() NS_ASSERTION(binding, "Prettyprint binding doesn't implement nsIObserver"); NS_ENSURE_TRUE(binding, NS_ERROR_UNEXPECTED); - return binding->Observe(resultDocument, "prettyprint-dom-created", NS_LITERAL_STRING("").get()); + return binding->Observe(resultFragment, "prettyprint-dom-created", NS_LITERAL_STRING("").get()); } @@ -558,6 +558,20 @@ nsXMLContentSink::DidBuildModel(PRInt32 aQualityLevel) return NS_OK; } +NS_IMETHODIMP +nsXMLContentSink::OnDocumentCreated(nsIDOMDocument* aResultDocument) +{ + NS_ENSURE_ARG(aResultDocument); + + nsCOMPtr docShell(do_QueryInterface(mWebShell)); + nsCOMPtr contentViewer; + docShell->GetContentViewer(getter_AddRefs(contentViewer)); + if (contentViewer) { + contentViewer->SetDOMDocument(aResultDocument); + } + return NS_OK; +} + NS_IMETHODIMP nsXMLContentSink::OnTransformDone(nsresult aResult, nsIDOMDocument* aResultDocument) @@ -636,32 +650,11 @@ nsXMLContentSink::OnTransformDone(nsresult aResult, nsresult nsXMLContentSink::SetupTransformMediator() { - nsresult rv = NS_OK; - nsCOMPtr currentDOMDoc(do_QueryInterface(mDocument)); mXSLTransformMediator->SetSourceContentModel(currentDOMDoc); - - // Create the result document - nsCOMPtr resultDOMDoc; - - nsCOMPtr url; - mDocument->GetBaseURL(*getter_AddRefs(url)); - - nsAutoString emptyStr; - rv = NS_NewDOMDocument(getter_AddRefs(resultDOMDoc), emptyStr, emptyStr, nsnull, url); - if (NS_FAILED(rv)) return rv; - - nsCOMPtr docShell(do_QueryInterface(mWebShell)); - nsCOMPtr contentViewer; - docShell->GetContentViewer(getter_AddRefs(contentViewer)); - if (contentViewer) { - contentViewer->SetDOMDocument(resultDOMDoc); - } - - mXSLTransformMediator->SetResultDocument(resultDOMDoc); mXSLTransformMediator->SetTransformObserver(this); - return rv; + return NS_OK; } NS_IMETHODIMP @@ -840,7 +833,9 @@ nsXMLContentSink::LoadXSLStyleSheet(nsIURI* aUrl) // httpChannel->SetReferrer(documentURI); } - // XXX need to set a load group on this channel! + nsCOMPtr loadGroup; + mDocument->GetDocumentLoadGroup(getter_AddRefs(loadGroup)); + channel->SetLoadGroup(loadGroup); return channel->AsyncOpen(sl, nsnull); } diff --git a/mozilla/content/xml/document/src/nsXMLContentSink.h b/mozilla/content/xml/document/src/nsXMLContentSink.h index bba91d8e851..9751c8f5314 100644 --- a/mozilla/content/xml/document/src/nsXMLContentSink.h +++ b/mozilla/content/xml/document/src/nsXMLContentSink.h @@ -57,7 +57,7 @@ class nsICSSStyleSheet; #include "nsIScriptLoaderObserver.h" #include "nsSupportsArray.h" #include "nsIExpatSink.h" -#include "nsITransformObserver.h" +#include "nsIDocumentTransformer.h" class nsIDocument; class nsIURI; @@ -99,7 +99,6 @@ public: // nsISupports NS_DECL_ISUPPORTS NS_DECL_NSISCRIPTLOADEROBSERVER - NS_DECL_NSITRANSFORMOBSERVER NS_DECL_NSIEXPATSINK // nsIContentSink @@ -114,6 +113,10 @@ public: // nsICSSLoaderObserver NS_IMETHOD StyleSheetLoaded(nsICSSStyleSheet*aSheet, PRBool aNotify); + // nsITransformObserver + NS_IMETHOD OnDocumentCreated(nsIDOMDocument *aResultDocument); + NS_IMETHOD OnTransformDone(nsresult aResult, nsIDOMDocument *aResultDocument); + protected: void StartLayout(); diff --git a/mozilla/content/xsl/Makefile.in b/mozilla/content/xsl/Makefile.in index 50464aa81ae..3c0e05b136f 100755 --- a/mozilla/content/xsl/Makefile.in +++ b/mozilla/content/xsl/Makefile.in @@ -21,7 +21,7 @@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk -DIRS = document +DIRS = public document include $(topsrcdir)/config/config.mk diff --git a/mozilla/content/xsl/document/Makefile.in b/mozilla/content/xsl/document/Makefile.in index b120f610dea..e98c66370c1 100755 --- a/mozilla/content/xsl/document/Makefile.in +++ b/mozilla/content/xsl/document/Makefile.in @@ -21,7 +21,7 @@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk -DIRS = public src +DIRS = src include $(topsrcdir)/config/config.mk diff --git a/mozilla/content/xsl/document/src/nsTransformMediator.cpp b/mozilla/content/xsl/document/src/nsTransformMediator.cpp index fa1042175f3..f6ceb701a6a 100644 --- a/mozilla/content/xsl/document/src/nsTransformMediator.cpp +++ b/mozilla/content/xsl/document/src/nsTransformMediator.cpp @@ -98,13 +98,13 @@ void nsTransformMediator::TryToTransform() { nsCOMPtr observer = do_QueryReferent(mObserver); - if (mSourceDOM && mStyleDOM && mResultDoc && observer) + if (mSourceDOM && mStyleDOM && observer) { if (mEnabled && mTransformer) { mTransformer->TransformDocument(mSourceDOM, mStyleDOM, - mResultDoc, - observer); + observer, + getter_AddRefs(mResultDoc)); } else if (mStyleInvalid) { // Avoid recursion. @@ -144,14 +144,6 @@ nsTransformMediator::SetStyleSheetContentModel(nsIDOMNode* aStyle) return NS_OK; } -NS_IMETHODIMP -nsTransformMediator::SetResultDocument(nsIDOMDocument* aDoc) -{ - mResultDoc = aDoc; - TryToTransform(); - return NS_OK; -} - NS_IMETHODIMP nsTransformMediator::GetResultDocument(nsIDOMDocument** aDoc) { diff --git a/mozilla/content/xsl/document/src/nsTransformMediator.h b/mozilla/content/xsl/document/src/nsTransformMediator.h index 8c631eba2e1..5643ba2e239 100644 --- a/mozilla/content/xsl/document/src/nsTransformMediator.h +++ b/mozilla/content/xsl/document/src/nsTransformMediator.h @@ -44,7 +44,6 @@ #include "nsIDocumentTransformer.h" #include "nsIDOMNode.h" #include "nsIDOMDocument.h" -#include "nsITransformObserver.h" #include "nsWeakPtr.h" class nsTransformMediator : public nsITransformMediator { @@ -61,7 +60,6 @@ public: NS_IMETHOD SetEnabled(PRBool aValue); NS_IMETHOD SetSourceContentModel(nsIDOMNode* aSource); NS_IMETHOD SetStyleSheetContentModel(nsIDOMNode* aStyle); - NS_IMETHOD SetResultDocument(nsIDOMDocument* aDoc); NS_IMETHOD GetResultDocument(nsIDOMDocument** aDoc); NS_IMETHOD SetTransformObserver(nsITransformObserver* aObserver); NS_IMETHOD SetStyleInvalid(PRBool aInvalid); diff --git a/mozilla/content/xsl/public/MANIFEST b/mozilla/content/xsl/public/MANIFEST new file mode 100644 index 00000000000..1664c6b2a45 --- /dev/null +++ b/mozilla/content/xsl/public/MANIFEST @@ -0,0 +1,6 @@ +# +# This is a list of local files which get copied to the mozilla:dist:content directory +# + +nsITransformMediator.h +nsIDocumentTransformer.h diff --git a/mozilla/content/xsl/public/MANIFEST_IDL b/mozilla/content/xsl/public/MANIFEST_IDL new file mode 100644 index 00000000000..805ee85cc75 --- /dev/null +++ b/mozilla/content/xsl/public/MANIFEST_IDL @@ -0,0 +1,8 @@ +# +# This is a list of local files which get copied to the mozilla:dist:idl directory +# + +nsIXSLTException.idl +nsIXSLTProcessor.idl +nsIXSLTProcessorObsolete.idl + diff --git a/mozilla/content/xsl/public/Makefile.in b/mozilla/content/xsl/public/Makefile.in new file mode 100644 index 00000000000..70d8fdfc402 --- /dev/null +++ b/mozilla/content/xsl/public/Makefile.in @@ -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 (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 + diff --git a/mozilla/content/xsl/public/nsIDocumentTransformer.h b/mozilla/content/xsl/public/nsIDocumentTransformer.h new file mode 100644 index 00000000000..28c83f14466 --- /dev/null +++ b/mozilla/content/xsl/public/nsIDocumentTransformer.h @@ -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 (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__ diff --git a/mozilla/content/xsl/public/nsITransformMediator.h b/mozilla/content/xsl/public/nsITransformMediator.h new file mode 100644 index 00000000000..090d943c0cf --- /dev/null +++ b/mozilla/content/xsl/public/nsITransformMediator.h @@ -0,0 +1,81 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** 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 (original author) + * Peter Van der Beken + * + * + * 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 nsITransformMediator_h___ +#define nsITransformMediator_h___ + +#include "nsISupports.h" +#include "nsAString.h" + +class nsIDOMNode; +class nsIDOMDocument; +class nsITransformObserver; +class nsIXMLContentSink; + +/* 6f4c2d0e-2cdf-11d3-aef3-00108300ff91 */ +#define NS_ITRANSFORM_MEDIATOR_IID \ +{ 0x6f4c2d0e, 0x2cdf, 0x11d3, {0xae, 0xf3, 0x00, 0x10, 0x83, 0x00, 0xff, 0x91} } + +/** + * This interface represents a mediator between Gecko and an external + * transformation engine. The following process of document transformation + * is assumed : a source document, a stylesheet specifying the transform, + * and an output document are passed to a transformation engine. All three + * documents expose nsIDOMDocument interfaces. The transformation engine + * uses the nsIDOMDocument interfaces to read the source document and + * stylesheet, and write the output document. + */ + +class nsITransformMediator : public nsISupports { +public: + NS_DEFINE_STATIC_IID_ACCESSOR(NS_ITRANSFORM_MEDIATOR_IID); + + NS_IMETHOD SetEnabled(PRBool aValue) = 0; + NS_IMETHOD SetSourceContentModel(nsIDOMNode* aSource) = 0; + NS_IMETHOD SetStyleSheetContentModel(nsIDOMNode* aStyle) = 0; + NS_IMETHOD GetResultDocument(nsIDOMDocument** aDoc) = 0; + NS_IMETHOD SetTransformObserver(nsITransformObserver* aObserver) = 0; + NS_IMETHOD SetStyleInvalid(PRBool aInvalid) = 0; +}; + +extern nsresult NS_NewTransformMediator(nsITransformMediator** aInstancePtrResult, + const nsACString& aMimeType); + +#endif // nsITransformMediator_h___ diff --git a/mozilla/content/xsl/public/nsIXSLTException.idl b/mozilla/content/xsl/public/nsIXSLTException.idl new file mode 100644 index 00000000000..0c291d1ad8f --- /dev/null +++ b/mozilla/content/xsl/public/nsIXSLTException.idl @@ -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, + * + * 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; +}; diff --git a/mozilla/content/xsl/public/nsIXSLTProcessor.idl b/mozilla/content/xsl/public/nsIXSLTProcessor.idl new file mode 100644 index 00000000000..c9616b0a67b --- /dev/null +++ b/mozilla/content/xsl/public/nsIXSLTProcessor.idl @@ -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, + * + * 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(); +}; diff --git a/mozilla/content/xsl/public/nsIXSLTProcessorObsolete.idl b/mozilla/content/xsl/public/nsIXSLTProcessorObsolete.idl new file mode 100644 index 00000000000..4ff46ae6f1b --- /dev/null +++ b/mozilla/content/xsl/public/nsIXSLTProcessorObsolete.idl @@ -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 (original author) + * Peter Van der Beken + * + * + * 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); +}; diff --git a/mozilla/extensions/transformiix/build/Makefile.in b/mozilla/extensions/transformiix/build/Makefile.in index ef519048184..6ad97dd58bc 100644 --- a/mozilla/extensions/transformiix/build/Makefile.in +++ b/mozilla/extensions/transformiix/build/Makefile.in @@ -46,6 +46,7 @@ REQUIRES = xpcom \ htmlparser \ webshell \ docshell \ + layout \ $(NULL) IS_COMPONENT = 1 MODULE_NAME = TransformiixModule @@ -116,9 +117,11 @@ LOBJS =../source/base/ArrayList.$(OBJ_SUFFIX) \ ../source/xslt/Names.$(OBJ_SUFFIX) \ ../source/xslt/ProcessorState.$(OBJ_SUFFIX) \ ../source/xslt/txMozillaTextOutput.$(OBJ_SUFFIX) \ + ../source/xslt/txMozillaXSLTProcessor.$(OBJ_SUFFIX) \ ../source/xslt/txMozillaXMLOutput.$(OBJ_SUFFIX) \ ../source/xslt/txRtfHandler.$(OBJ_SUFFIX) \ ../source/xslt/txTextHandler.$(OBJ_SUFFIX) \ + ../source/xslt/txUnknownHandler.$(OBJ_SUFFIX) \ ../source/xslt/txXSLTNumber.$(OBJ_SUFFIX) \ ../source/xslt/txXSLTNumberCounters.$(OBJ_SUFFIX) \ ../source/xslt/txXSLTPatterns.$(OBJ_SUFFIX) \ diff --git a/mozilla/extensions/transformiix/build/XSLTProcessorModule.cpp b/mozilla/extensions/transformiix/build/XSLTProcessorModule.cpp index 91d438c2ef8..65492a8d850 100755 --- a/mozilla/extensions/transformiix/build/XSLTProcessorModule.cpp +++ b/mozilla/extensions/transformiix/build/XSLTProcessorModule.cpp @@ -1,4 +1,5 @@ -/* +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * * 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 @@ -36,7 +37,7 @@ #include "nsXPathResult.h" #include "nsXPIDLString.h" #include "txAtoms.h" -#include "XSLTProcessor.h" +#include "txMozillaXSLTProcessor.h" #include "TxLog.h" #include "nsCRT.h" #include "nsIScriptSecurityManager.h" @@ -49,13 +50,13 @@ #define TRANSFORMIIX_DOMCI_EXTENSION_CONTRACTID \ "@mozilla.org/transformiix-domci-extender;1" - NS_DOMCI_EXTENSION(Transformiix) static NS_DEFINE_CID(kXSLTProcessorCID, TRANSFORMIIX_XSLT_PROCESSOR_CID); NS_DOMCI_EXTENSION_ENTRY_BEGIN(XSLTProcessor) - NS_DOMCI_EXTENSION_ENTRY_INTERFACE(nsIDocumentTransformer) - NS_DOMCI_EXTENSION_ENTRY_END(XSLTProcessor, nsIDocumentTransformer, - PR_FALSE, &kXSLTProcessorCID) + NS_DOMCI_EXTENSION_ENTRY_INTERFACE(nsIXSLTProcessor) + NS_DOMCI_EXTENSION_ENTRY_INTERFACE(nsIXSLTProcessorObsolete) // XXX DEPRECATED + NS_DOMCI_EXTENSION_ENTRY_END(XSLTProcessor, nsIXSLTProcessor, PR_TRUE, + &kXSLTProcessorCID) static NS_DEFINE_CID(kXPathEvaluatorCID, TRANSFORMIIX_XPATH_EVALUATOR_CID); NS_DOMCI_EXTENSION_ENTRY_BEGIN(XPathEvaluator) @@ -86,7 +87,7 @@ NS_DOMCI_EXTENSION(Transformiix) NS_DOMCI_EXTENSION_END // Factory Constructor -NS_GENERIC_FACTORY_CONSTRUCTOR(XSLTProcessor) +NS_GENERIC_FACTORY_CONSTRUCTOR(txMozillaXSLTProcessor) NS_GENERIC_FACTORY_CONSTRUCTOR(nsXPathEvaluator) NS_DECL_DOM_CLASSINFO(XSLTProcessor) @@ -148,11 +149,21 @@ RegisterTransformiix(nsIComponentManager *aCompMgr, PR_TRUE, PR_TRUE, getter_Copies(previous)); NS_ENSURE_SUCCESS(rv, rv); - char* iidString = NS_GET_IID(nsIDocumentTransformer).ToString(); + char* iidString = NS_GET_IID(nsIXSLTProcessorObsolete).ToString(); if (!iidString) return NS_ERROR_OUT_OF_MEMORY; rv = catman->AddCategoryEntry(JAVASCRIPT_DOM_INTERFACE, - "nsIDocumentTransformer", + "nsIXSLTProcessorObsolete", + iidString, + PR_TRUE, PR_TRUE, getter_Copies(previous)); + nsCRT::free(iidString); + NS_ENSURE_SUCCESS(rv, rv); + + iidString = NS_GET_IID(nsIXSLTProcessor).ToString(); + if (!iidString) + return NS_ERROR_OUT_OF_MEMORY; + rv = catman->AddCategoryEntry(JAVASCRIPT_DOM_INTERFACE, + "nsIXSLTProcessor", iidString, PR_TRUE, PR_TRUE, getter_Copies(previous)); nsCRT::free(iidString); @@ -169,7 +180,6 @@ PR_STATIC_CALLBACK(nsresult) Initialize(nsIModule* aSelf) { NS_PRECONDITION(!gInitialized, "module already initialized"); - nsresult rv = NS_OK; if (gInitialized) return NS_OK; @@ -185,16 +195,12 @@ Initialize(nsIModule* aSelf) xs->RegisterExceptionProvider(sXPathExceptionProvider, NS_ERROR_MODULE_DOM_XPATH); - if (!txXMLAtoms::init()) - return NS_ERROR_OUT_OF_MEMORY; - if (!txXPathAtoms::init()) - return NS_ERROR_OUT_OF_MEMORY; - if (!txXSLTAtoms::init()) - return NS_ERROR_OUT_OF_MEMORY; - if (!txHTMLAtoms::init()) + if (!txXSLTProcessor::txInit()) { return NS_ERROR_OUT_OF_MEMORY; + } - rv = CallGetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &gTxSecurityManager); + nsresult rv = CallGetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, + &gTxSecurityManager); if (NS_FAILED(rv)) { gTxSecurityManager = nsnull; return rv; @@ -230,10 +236,7 @@ Shutdown(nsIModule* aSelf) NS_IF_RELEASE(NS_CLASSINFO_NAME(XPathNSResolver)); NS_IF_RELEASE(NS_CLASSINFO_NAME(XPathResult)); - txXMLAtoms::shutdown(); - txXPathAtoms::shutdown(); - txXSLTAtoms::shutdown(); - txHTMLAtoms::shutdown(); + txXSLTProcessor::txShutdown(); NS_IF_RELEASE(gTxSecurityManager); @@ -245,7 +248,7 @@ static const nsModuleComponentInfo gComponents[] = { { "XSLTProcessor", TRANSFORMIIX_XSLT_PROCESSOR_CID, TRANSFORMIIX_XSLT_PROCESSOR_CONTRACTID, - XSLTProcessorConstructor, + txMozillaXSLTProcessorConstructor, RegisterTransformiix }, { "XPathEvaluator", TRANSFORMIIX_XPATH_EVALUATOR_CID, diff --git a/mozilla/extensions/transformiix/macbuild/transformiix.xml b/mozilla/extensions/transformiix/macbuild/transformiix.xml index 5db9f47f21e..e39685c6ab1 100644 --- a/mozilla/extensions/transformiix/macbuild/transformiix.xml +++ b/mozilla/extensions/transformiix/macbuild/transformiix.xml @@ -1587,6 +1587,20 @@ Text Debug + + Name + txMozillaXSLTProcessor.cpp + MacOS + Text + Debug + + + Name + txUnknownHandler.cpp + MacOS + Text + + @@ -2039,6 +2053,16 @@ txXSLTPatterns.cpp MacOS + + Name + txMozillaXSLTProcessor.cpp + MacOS + + + Name + txUnknownHandler.cpp + MacOS + @@ -3575,6 +3599,20 @@ Text Debug + + Name + txMozillaXSLTProcessor.cpp + MacOS + Text + Debug + + + Name + txUnknownHandler.cpp + MacOS + Text + Debug + @@ -4027,6 +4065,16 @@ txXSLTPatterns.cpp MacOS + + Name + txMozillaXSLTProcessor.cpp + MacOS + + + Name + txUnknownHandler.cpp + MacOS + @@ -4433,6 +4481,12 @@ txMozillaXMLOutput.cpp MacOS + + transformiixDebug.shlb + Name + txMozillaXSLTProcessor.cpp + MacOS + transformiixDebug.shlb Name @@ -4457,6 +4511,12 @@ txTextHandler.cpp MacOS + + transformiixDebug.shlb + Name + txUnknownHandler.cpp + MacOS + transformiixDebug.shlb Name diff --git a/mozilla/extensions/transformiix/source/main/Makefile.in b/mozilla/extensions/transformiix/source/main/Makefile.in index 74a92535572..4f44b72b24f 100644 --- a/mozilla/extensions/transformiix/source/main/Makefile.in +++ b/mozilla/extensions/transformiix/source/main/Makefile.in @@ -26,7 +26,14 @@ VPATH = @srcdir@ 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 \ $(NULL) @@ -109,6 +116,7 @@ OBJS =../base/ArrayList.$(OBJ_SUFFIX) \ ../xslt/txXSLTPatterns.$(OBJ_SUFFIX) \ ../xslt/txPatternParser.$(OBJ_SUFFIX) \ ../xslt/XSLTProcessor.$(OBJ_SUFFIX) \ + ../xslt/txStandaloneXSLTProcessor.$(OBJ_SUFFIX) \ ../xslt/functions/CurrentFunctionCall.$(OBJ_SUFFIX) \ ../xslt/functions/DocumentFunctionCall.$(OBJ_SUFFIX) \ ../xslt/functions/ElementAvailableFnCall.$(OBJ_SUFFIX) \ @@ -118,11 +126,13 @@ OBJS =../base/ArrayList.$(OBJ_SUFFIX) \ ../xslt/functions/txFormatNumberFunctionCall.$(OBJ_SUFFIX) \ ../xslt/functions/txKeyFunctionCall.$(OBJ_SUFFIX) \ ../xslt/util/txNodeSorter.$(OBJ_SUFFIX) \ - ../xslt/util/txXPathResultComparator.$(OBJ_SUFFIX) \ - transformiix.$(OBJ_SUFFIX) + ../xslt/util/txXPathResultComparator.$(OBJ_SUFFIX) CPP_PROG_LINK = 1 EXTRA_LIBS = \ + $(LIB_PREFIX)tx.$(LIB_SUFFIX) \ + $(NULL) +SHARED_LIBRARY_LIBS = \ $(DIST)/lib/$(LIB_PREFIX)expat_s.$(LIB_SUFFIX) \ $(DIST)/lib/$(LIB_PREFIX)xmltok_s.$(LIB_SUFFIX) \ $(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/parser \ -I$(srcdir)/../xpath -I$(srcdir)/../xslt/util \ - -I$(srcdir)/../xslt/functions \ No newline at end of file + -I$(srcdir)/../xslt/functions $(MARK_INC) diff --git a/mozilla/extensions/transformiix/source/main/transformiix.cpp b/mozilla/extensions/transformiix/source/main/transformiix.cpp index e96a90e58cd..e4fb0662fc0 100644 --- a/mozilla/extensions/transformiix/source/main/transformiix.cpp +++ b/mozilla/extensions/transformiix/source/main/transformiix.cpp @@ -29,14 +29,13 @@ * * Olivier Gerardin, ogerardin@vo.lu * -- 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 //--------------/ //- Prototypes -/ @@ -57,13 +56,8 @@ void printUsage(); **/ int main(int argc, char** argv) { - if (!txInit()) + if (!txXSLTProcessor::txInit()) return 1; - XSLTProcessor xsltProcessor; - - //-- add ErrorObserver - SimpleErrorObserver seo; - xsltProcessor.addErrorObserver(seo); //-- available flags StringList flags; @@ -79,8 +73,8 @@ int main(int argc, char** argv) { if (!options.get(String("q"))) { String copyright("(C) 1999 The MITRE Corporation, Keith Visco, and contributors"); - cerr << xsltProcessor.getAppName() << " "; - cerr << xsltProcessor.getAppVersion() << endl; + cerr << "TransforMiiX "; + cerr << "1.2b pre" << endl; cerr << copyright << endl; //-- print banner line PRUint32 fillSize = copyright.length() + 1; @@ -98,63 +92,52 @@ int main(int argc, char** argv) { String* xsltFilename = (String*)options.get(String("s")); 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 ostream* resultOutput = &cout; ofstream resultFileStream; - if ( outFilename && ! outFilename->isEqual("-")) { + if (outFilename && !outFilename->isEqual("-")) { resultFileStream.open(NS_LossyConvertUCS2toASCII(*outFilename).get(), ios::out); - if ( !resultFileStream ) { + if (!resultFileStream) { cerr << "error opening output file: " << *xmlFilename << endl; return -1; } resultOutput = &resultFileStream; } + SimpleErrorObserver obs; + txStandaloneXSLTProcessor proc; + nsresult rv = NS_OK; //-- process - String documentBase; - if ( !xsltFilename ) { - if (!xmlFilename) { - cerr << "you must specify XSLT file with -s option if XML is read from standard input" << endl; - printUsage(); - return -1; - } - xsltProcessor.process(*xmlInput, *xmlFilename, *resultOutput); + if (!xsltFilename) { + if (!xmlFilename) { + cerr << "you must specify at least a source XML path" << endl; + printUsage(); + return -1; + } + rv = proc.transform(*xmlFilename, *resultOutput, obs); } else { //-- open XSLT file - ifstream xsltInput(NS_LossyConvertUCS2toASCII(*xsltFilename).get(), - ios::in); - xsltProcessor.process(*xmlInput, *xmlFilename, xsltInput, *xsltFilename, *resultOutput); + rv = proc.transform(*xmlFilename, *xsltFilename, *resultOutput, obs); } resultFileStream.close(); - if (xmlInput != &cin) - delete xmlInput; - txShutdown(); - return 0; + txXSLTProcessor::txShutdown(); + return NS_SUCCEEDED(rv); } //-- main void printHelp() { cerr << "transfrmx [-h] [-i xml-file] [-s xslt-file] [-o output-file]" << endl << endl; cerr << "Options:"; 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 << "\t\tspecified in XML file)" << endl; cerr << "\t-o specify output file (default: write to stdout)" << endl; cerr << "\t-h this help screen" << endl; cerr << endl; - cerr << "You may use '-' in place of xml-file or output-file to explicitly specify" << endl; - cerr << "respectively the standard input and standard output." << endl; - cerr << "If the XML is read from stdin, then the -s option is mandatory." << endl; + cerr << "You may use '-' in place of the output-file to explicitly specify" << endl; + cerr << "standard output." << endl; cerr << endl; } void printUsage() { diff --git a/mozilla/extensions/transformiix/source/main/txXSLTMarkDriver.cpp b/mozilla/extensions/transformiix/source/main/txXSLTMarkDriver.cpp new file mode 100644 index 00000000000..7d45c812b58 --- /dev/null +++ b/mozilla/extensions/transformiix/source/main/txXSLTMarkDriver.cpp @@ -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 (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; +} diff --git a/mozilla/extensions/transformiix/source/xpath/nsXPathEvaluator.cpp b/mozilla/extensions/transformiix/source/xpath/nsXPathEvaluator.cpp index 828067356ee..83a38992693 100644 --- a/mozilla/extensions/transformiix/source/xpath/nsXPathEvaluator.cpp +++ b/mozilla/extensions/transformiix/source/xpath/nsXPathEvaluator.cpp @@ -154,7 +154,7 @@ nsresult nsXPathEvaluator::ParseContextImpl::resolveNamespacePrefix } if (!mNSMan) { - mNSMan = do_CreateInstance(kNameSpaceManagerCID); + mNSMan = do_GetService(kNameSpaceManagerCID); if (!mNSMan) { return NS_ERROR_FAILURE; } diff --git a/mozilla/extensions/transformiix/source/xslt/Makefile.in b/mozilla/extensions/transformiix/source/xslt/Makefile.in index 931de870120..31113ade88a 100644 --- a/mozilla/extensions/transformiix/source/xslt/Makefile.in +++ b/mozilla/extensions/transformiix/source/xslt/Makefile.in @@ -42,6 +42,7 @@ REQUIRES = string \ htmlparser \ webshell \ docshell \ + layout \ $(NULL) endif @@ -54,16 +55,18 @@ CPPSRCS = Names.cpp \ txXSLTNumberCounters.cpp \ txXSLTPatterns.cpp \ txPatternParser.cpp \ + txUnknownHandler.cpp \ XSLTProcessor.cpp ifdef TX_EXE CPPSRCS += txHTMLOutput.cpp \ + txStandaloneXSLTProcessor.cpp \ txTextOutput.cpp \ - txUnknownHandler.cpp \ txXMLOutput.cpp else CPPSRCS += txMozillaTextOutput.cpp \ - txMozillaXMLOutput.cpp + txMozillaXMLOutput.cpp \ + txMozillaXSLTProcessor.cpp endif include $(topsrcdir)/config/rules.mk diff --git a/mozilla/extensions/transformiix/source/xslt/ProcessorState.cpp b/mozilla/extensions/transformiix/source/xslt/ProcessorState.cpp index afe73af6380..8b71be6f9b7 100644 --- a/mozilla/extensions/transformiix/source/xslt/ProcessorState.cpp +++ b/mozilla/extensions/transformiix/source/xslt/ProcessorState.cpp @@ -44,17 +44,15 @@ #include "XMLParser.h" #include "TxLog.h" #include "txAtoms.h" -#include "XSLTProcessor.h" #include "txSingleNodeContext.h" #include "txVariableMap.h" +#include "XSLTProcessor.h" /** * Creates a new ProcessorState for the given XSL document - * and resultDocument **/ ProcessorState::ProcessorState(Document* aSourceDocument, - Document* aXslDocument, - Document* aResultDocument) + Document* aXslDocument) : mXslKeys(MB_TRUE), mDecimalFormats(MB_TRUE), mEvalContext(0), @@ -62,11 +60,13 @@ ProcessorState::ProcessorState(Document* aSourceDocument, mGlobalVariableValues(MB_TRUE), mSourceDocument(aSourceDocument), xslDocument(aXslDocument), - resultDocument(aResultDocument) + mRTFDocument(0), + mOutputHandler(0), + mResultHandler(0), + mOutputHandlerFactory(0) { NS_ASSERTION(aSourceDocument, "missing source document"); NS_ASSERTION(aXslDocument, "missing xslt document"); - NS_ASSERTION(aResultDocument, "missing result document"); /* turn object deletion on for some of the Maps (NamedMap) */ mExprHashes[SelectAttr].setOwnership(Map::eOwnsItems); @@ -104,6 +104,10 @@ ProcessorState::~ProcessorState() if (mSourceDocument) loadedDocuments.remove(mSourceDocument->getBaseURI()); + // in module the outputhandler is refcounted +#ifdef TX_EXE + delete mOutputHandler; +#endif } //-- ~ProcessorState @@ -635,26 +639,48 @@ txOutputFormat* ProcessorState::getOutputFormat() return &mOutputFormat; } -Document* ProcessorState::getResultDocument() +Document* ProcessorState::getRTFDocument() { - return resultDocument; + return mRTFDocument; +} + +void ProcessorState::setRTFDocument(Document* aDoc) +{ + mRTFDocument = aDoc; +} + +Document* ProcessorState::getStylesheetDocument() +{ + NS_ASSERTION(xslDocument, "missing stylesheet document"); + return xslDocument; } /* * Add a global variable */ -nsresult ProcessorState::addGlobalVariable(Element* aVarElem, - ImportFrame* aImportFrame) +nsresult ProcessorState::addGlobalVariable(const txExpandedName& aVarName, + Element* aVarElem, + ImportFrame* aImportFrame, + ExprResult* aDefaultValue) { - nsresult rv; - txExpandedName varName; - String qName; - aVarElem->getAttr(txXSLTAtoms::name, kNameSpaceID_None, qName); - rv = varName.init(qName, aVarElem, MB_FALSE); - if (NS_FAILED(rv)) - return rv; + // If we don't know the value, it's a plain global var, add it + // to the import frame for late evaluation. + if (!aDefaultValue) { + return aImportFrame->mVariables.add(aVarName, aVarElem); + } + // Otherwise, add a GlobalVariableValue not owning the value. + GlobalVariableValue* var = + (GlobalVariableValue*)mGlobalVariableValues.get(aVarName); + if (var) { + // we set this parameter twice, we should set it to the same + // value; + NS_ENSURE_TRUE(var->mValue == aDefaultValue, NS_ERROR_UNEXPECTED); + return NS_OK; + } + var = new GlobalVariableValue(aDefaultValue); + NS_ENSURE_TRUE(var, NS_ERROR_OUT_OF_MEMORY); - return aImportFrame->mVariables.add(varName, aVarElem); + return mGlobalVariableValues.add(aVarName, var); } /* @@ -950,7 +976,7 @@ nsresult ProcessorState::getVariable(PRInt32 aNamespace, txAtom* aLName, GlobalVariableValue* globVar; globVar = (GlobalVariableValue*)mGlobalVariableValues.get(varName); if (globVar) { - if (globVar->mEvaluating) { + if (globVar->mFlags == GlobalVariableValue::evaluating) { String err("Cyclic variable-value detected"); receiveError(err, NS_ERROR_FAILURE); return NS_ERROR_FAILURE; @@ -975,7 +1001,6 @@ nsresult ProcessorState::getVariable(PRInt32 aNamespace, txAtom* aLName, globVar = new GlobalVariableValue(); if (!globVar) return NS_ERROR_OUT_OF_MEMORY; - globVar->mEvaluating = MB_TRUE; rv = mGlobalVariableValues.add(varName, globVar); if (NS_FAILED(rv)) { delete globVar; @@ -987,12 +1012,14 @@ nsresult ProcessorState::getVariable(PRInt32 aNamespace, txAtom* aLName, mLocalVariables = 0; txSingleNodeContext evalContext(mSourceDocument, this); txIEvalContext* priorEC = setEvalContext(&evalContext); - XSLTProcessor processor; - globVar->mValue = processor.processVariable(varElem, this); + // Compute the variable value + globVar->mFlags = GlobalVariableValue::evaluating; + globVar->mValue = txXSLTProcessor::processVariable(varElem, this); setEvalContext(priorEC); mLocalVariables = oldVars; - globVar->mEvaluating = MB_FALSE; + // evaluation is over, the gvv now owns the ExprResult + globVar->mFlags = GlobalVariableValue::owned; aResult = globVar->mValue; return NS_OK; } @@ -1178,5 +1205,8 @@ void txPSParseContext::receiveError(const String& aMsg, nsresult aRes) ProcessorState::GlobalVariableValue::~GlobalVariableValue() { - delete mValue; + NS_ASSERTION(mFlags != evaluating, "deleted while evaluating"); + if (mFlags == owned) { + delete mValue; + } } diff --git a/mozilla/extensions/transformiix/source/xslt/ProcessorState.h b/mozilla/extensions/transformiix/source/xslt/ProcessorState.h index dd7b4f8df07..b7ba673058e 100644 --- a/mozilla/extensions/transformiix/source/xslt/ProcessorState.h +++ b/mozilla/extensions/transformiix/source/xslt/ProcessorState.h @@ -39,6 +39,7 @@ #include "Map.h" #include "txIXPathContext.h" #include "txExpandedNameMap.h" +#include "txXMLEventHandler.h" #include "XSLTFunctions.h" #include "txError.h" @@ -56,8 +57,7 @@ public: * And result Document */ ProcessorState(Document* aSourceDocument, - Document* aXslDocument, - Document* aResultDocument); + Document* aXslDocument); /** * Destroys this ProcessorState @@ -134,11 +134,6 @@ public: */ NodeSet* getAttributeSet(const txExpandedName& aName); - /** - * Returns the source node currently being processed - */ - Node* getCurrentNode(); - /** * Returns the template associated with the given name, or * null if not template is found @@ -154,8 +149,10 @@ public: /** * Add a global variable */ - nsresult addGlobalVariable(Element* aVarElem, - ImportFrame* aImportFrame); + nsresult addGlobalVariable(const txExpandedName& aVarName, + Element* aVarElem, + ImportFrame* aImportFrame, + ExprResult* aDefaultValue); /** * Returns map on top of the stack of local variable-bindings @@ -184,11 +181,6 @@ public: Expr* getExpr(Element* aElem, ExprAttr aAttr); txPattern* getPattern(Element* aElem, PatternAttr aAttr); - /** - * Returns a pointer to the result document - */ - Document* getResultDocument(); - /** * Retrieve the document designated by the URI uri, using baseUri as base URI. * Parses it as an XML document, and returns it. If a fragment identifier is @@ -303,6 +295,21 @@ public: */ txDecimalFormat* getDecimalFormat(const txExpandedName& name); + /** + * Returns a pointer to a document that can be used to create RTFs + */ + Document* getRTFDocument(); + + /** + * Sets a new document to be used for creating RTFs + */ + void setRTFDocument(Document* aDoc); + + /** + * Returns the stylesheet document + */ + Document* getStylesheetDocument(); + /** * Virtual methods from txIEvalContext */ @@ -343,6 +350,15 @@ public: nsresult resolveFunctionCall(txAtom* aName, PRInt32 aID, Element* aElem, FunctionCall*& aFunction); +#ifdef TX_EXE + txIOutputXMLEventHandler* mOutputHandler; +#else + nsCOMPtr mOutputHandler; +#endif + txXMLEventHandler* mResultHandler; + + txIOutputHandlerFactory* mOutputHandlerFactory; + private: class MatchableTemplate { @@ -359,10 +375,20 @@ private: class GlobalVariableValue : public TxObject { public: + GlobalVariableValue(ExprResult* aValue = 0) + : mValue(aValue), mFlags(nonOwned) + { + } virtual ~GlobalVariableValue(); ExprResult* mValue; - MBool mEvaluating; + char mFlags; + enum _flags + { + nonOwned = 0, + evaluating, + owned + }; }; /** @@ -440,7 +466,11 @@ private: Document* mSourceDocument; Document* xslDocument; - Document* resultDocument; + + /** + * Document used to create RTFs + */ + Document* mRTFDocument; }; /** diff --git a/mozilla/extensions/transformiix/source/xslt/XSLTProcessor.cpp b/mozilla/extensions/transformiix/source/xslt/XSLTProcessor.cpp index 9b506f47722..a74ab5f636e 100644 --- a/mozilla/extensions/transformiix/source/xslt/XSLTProcessor.cpp +++ b/mozilla/extensions/transformiix/source/xslt/XSLTProcessor.cpp @@ -43,53 +43,29 @@ #include "XSLTProcessor.h" #include "Names.h" -#include "XMLParser.h" -#include "txVariableMap.h" -#include "XMLUtils.h" -#include "XMLDOMUtils.h" -#include "txNodeSorter.h" -#include "txXSLTNumber.h" #include "Tokenizer.h" -#include "txURIUtils.h" #include "txAtoms.h" #include "TxLog.h" -#include "txRtfHandler.h" #include "txNodeSetContext.h" -#include "txSingleNodeContext.h" +#include "txNodeSorter.h" +#include "txRtfHandler.h" +#include "txTextHandler.h" +#include "txURIUtils.h" +#include "txVariableMap.h" +#include "txXSLTNumber.h" +#include "XMLDOMUtils.h" +#include "XMLUtils.h" + #ifndef TX_EXE -#include "nsIDocShell.h" -#include "nsIDocument.h" -#include "nsIObserverService.h" -#include "nsIURL.h" -#include "nsIServiceManager.h" -#include "nsIIOService.h" -#include "nsILoadGroup.h" -#include "nsIChannel.h" -#include "nsNetUtil.h" -#include "nsIDOMClassInfo.h" +#include "nsContentCID.h" #include "nsIConsoleService.h" -#include "nsDOMError.h" -#else -#include "txHTMLOutput.h" -#include "txTextOutput.h" -#include "txUnknownHandler.h" -#include "txXMLOutput.h" +#include "nsIDOMDocument.h" +#include "nsIServiceManagerUtils.h" + +static NS_DEFINE_CID(kXMLDocumentCID, NS_XMLDOCUMENT_CID); #endif - //-----------------------------------/ - //- Implementation of XSLTProcessor -/ -//-----------------------------------/ - -/** - * XSLTProcessor is a class for Processing XSL stylesheets -**/ - -/** - * A warning message used by all templates that do not allow non character - * data to be generated -**/ -const String XSLTProcessor::NON_TEXT_TEMPLATE_WARNING( -"templates for the following element are not allowed to generate non character data: "); +Expr* txXSLTProcessor::gNodeExpr = 0; /* * Implement static variables for atomservice and dom. @@ -99,65 +75,26 @@ TX_IMPL_ATOM_STATICS; TX_IMPL_DOM_STATICS; #endif -/** - * Creates a new XSLTProcessor -**/ -XSLTProcessor::XSLTProcessor() : mOutputHandler(0), - mResultHandler(0) -{ -#ifndef TX_EXE - NS_INIT_ISUPPORTS(); -#endif - - xslVersion.append("1.0"); - appName.append("TransforMiiX"); - appVersion.append("1.0 [beta v20010123]"); - - // Create default expressions - - // "node()" - txNodeTest* nt = new txNodeTypeTest(txNodeTypeTest::NODE_TYPE); - mNodeExpr = new LocationStep(nt, LocationStep::CHILD_AXIS); - -} //-- XSLTProcessor - -/** - * Default destructor -**/ -XSLTProcessor::~XSLTProcessor() -{ - delete mOutputHandler; - delete mNodeExpr; -} - -#ifndef TX_EXE - -// XXX START -// XXX Mozilla module only code. This should move to txMozillaXSLTProcessor -// XXX - -NS_IMPL_ADDREF(XSLTProcessor) -NS_IMPL_RELEASE(XSLTProcessor) -NS_INTERFACE_MAP_BEGIN(XSLTProcessor) - NS_INTERFACE_MAP_ENTRY(nsIDocumentTransformer) - NS_INTERFACE_MAP_ENTRY(nsIScriptLoaderObserver) - NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDocumentTransformer) - NS_INTERFACE_MAP_ENTRY_EXTERNAL_DOM_CLASSINFO(XSLTProcessor) -NS_INTERFACE_MAP_END - -// XXX -// XXX Mozilla module only code. This should move to txMozillaXSLTProcessor -// XXX END - -#else - -/* - * Initialize atom tables. - */ -MBool txInit() +/* static */ +MBool +txXSLTProcessor::txInit() { +#ifdef TX_EXE if (!txNamespaceManager::init()) return MB_FALSE; +#endif + + // Create default expressions + // "node()" + txNodeTest* nt = new txNodeTypeTest(txNodeTypeTest::NODE_TYPE); + if (!nt) { + return MB_FALSE; + } + gNodeExpr = new LocationStep(nt, LocationStep::CHILD_AXIS); + if (!gNodeExpr) { + return MB_FALSE; + } + if (!txHTMLAtoms::init()) return MB_FALSE; if (!txXMLAtoms::init()) @@ -167,230 +104,25 @@ MBool txInit() return txXSLTAtoms::init(); } -/* - * To be called when done with transformiix. - * - * Free atom table, namespace manager. - */ -MBool txShutdown() +/* static */ +MBool +txXSLTProcessor::txShutdown() { +#ifdef TX_EXE txNamespaceManager::shutdown(); +#endif + + delete gNodeExpr; + txHTMLAtoms::shutdown(); txXMLAtoms::shutdown(); txXPathAtoms::shutdown(); txXSLTAtoms::shutdown(); return MB_TRUE; } -#endif - -/** - * Registers the given ErrorObserver with this ProcessorState -**/ -void XSLTProcessor::addErrorObserver(ErrorObserver& errorObserver) { - errorObservers.add(&errorObserver); -} //-- addErrorObserver - -String& XSLTProcessor::getAppName() { - return appName; -} //-- getAppName - -String& XSLTProcessor::getAppVersion() { - return appVersion; -} //-- getAppVersion - -#ifdef TX_EXE - -// XXX START -// XXX Standalone only code. This should move to txStandaloneXSLTProcessor -// XXX - -/** - * 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 XSLTProcessor::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(); - } - -} //-- getHrefFromStylesheetPI - -/** - * Parses the contents of data, and returns the type and href psuedo attributes -**/ -void XSLTProcessor::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; - UNICODE_CHAR matchQuote = '"'; - String sink; - String* buffer = &sink; - - for (ccount = 0; ccount < size; ccount++) { - UNICODE_CHAR ch = data.charAt(ccount); - switch ( ch ) { - case ' ' : - if ( inLiteral ) { - buffer->append(ch); - } - break; - case '=': - if ( inLiteral ) buffer->append(ch); - else if (!buffer->isEmpty()) { - 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; - } - } - -} //-- parseStylesheetPI - -/** - * Processes the given XML Document, the XSL stylesheet - * will be retrieved from the XML Stylesheet Processing instruction, - * otherwise an empty document will be returned. - * @param xmlDocument the XML document to process - * @param documentBase the document base of the XML document, for - * resolving relative URIs - * @return the result tree. -**/ -Document* XSLTProcessor::process(Document& xmlDocument) { - //-- look for Stylesheet PI - Document xslDocument; //-- empty for now - return process(xmlDocument, xslDocument); -} //-- process - -/** - * Reads an XML Document from the given XML input stream, and - * processes the document using the XSL document derived from - * the given XSL input stream. - * @return the result tree. -**/ -Document* XSLTProcessor::process - (istream& xmlInput, String& xmlFilename, - istream& xslInput, String& xslFilename) { - //-- read in XML Document - XMLParser xmlParser; - Document* xmlDoc = xmlParser.parse(xmlInput, xmlFilename); - if (!xmlDoc) { - String err("error reading XML document: "); - err.append(xmlParser.getErrorString()); - cerr << err << endl; - return 0; - } - //-- Read in XSL document - Document* xslDoc = xmlParser.parse(xslInput, xslFilename); - if (!xslDoc) { - String err("error reading XSL stylesheet document: "); - err.append(xmlParser.getErrorString()); - cerr << err << endl; - delete xmlDoc; - return 0; - } - Document* result = process(*xmlDoc, *xslDoc); - delete xmlDoc; - delete xslDoc; - return result; -} //-- process - -/** - * Reads an XML document from the given XML input stream. The - * XML document is processed using the associated XSL document - * retrieved from the XML document's Stylesheet Processing Instruction, - * otherwise an empty document will be returned. - * @param xmlDocument the XML document to process - * @param documentBase the document base of the XML document, for - * resolving relative URIs - * @return the result tree. -**/ -Document* XSLTProcessor::process(istream& xmlInput, String& xmlFilename) { - //-- read in XML Document - XMLParser xmlParser; - Document* xmlDoc = xmlParser.parse(xmlInput, xmlFilename); - if (!xmlDoc) { - String err("error reading XML document: "); - err.append(xmlParser.getErrorString()); - cerr << err << endl; - return 0; - } - //-- Read in XSL document - String href; - String errMsg; - getHrefFromStylesheetPI(*xmlDoc, href); - istream* xslInput = URIUtils::getInputStream(href,errMsg); - Document* xslDoc = 0; - if ( xslInput ) { - xslDoc = xmlParser.parse(*xslInput, href); - delete xslInput; - } - if (!xslDoc) { - String err("error reading XSL stylesheet document: "); - err.append(xmlParser.getErrorString()); - cerr << err << endl; - delete xmlDoc; - return 0; - } - Document* result = process(*xmlDoc, *xslDoc); - delete xmlDoc; - delete xslDoc; - return result; -} //-- process - -// XXX -// XXX Standalone only code. This should move to txStandaloneXSLTProcessor -// XXX END - -#endif void -XSLTProcessor::copyNode(Node* aSourceNode, ProcessorState* aPs) +txXSLTProcessor::copyNode(Node* aSourceNode, ProcessorState* aPs) { if (!aSourceNode) return; @@ -398,16 +130,16 @@ XSLTProcessor::copyNode(Node* aSourceNode, ProcessorState* aPs) switch (aSourceNode->getNodeType()) { case Node::ATTRIBUTE_NODE: { - NS_ASSERTION(mResultHandler, "mResultHandler must not be NULL!"); - mResultHandler->attribute(aSourceNode->getNodeName(), - aSourceNode->getNamespaceID(), - aSourceNode->getNodeValue()); + NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); + aPs->mResultHandler->attribute(aSourceNode->getNodeName(), + aSourceNode->getNamespaceID(), + aSourceNode->getNodeValue()); break; } case Node::COMMENT_NODE: { - NS_ASSERTION(mResultHandler, "mResultHandler must not be NULL!"); - mResultHandler->comment(aSourceNode->getNodeValue()); + NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); + aPs->mResultHandler->comment(aSourceNode->getNodeValue()); break; } case Node::DOCUMENT_NODE: @@ -426,7 +158,8 @@ XSLTProcessor::copyNode(Node* aSourceNode, ProcessorState* aPs) Element* element = (Element*)aSourceNode; const String& name = element->getNodeName(); PRInt32 nsID = element->getNamespaceID(); - startElement(name, nsID, aPs); + NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); + aPs->mResultHandler->startElement(name, nsID); // Copy attributes NamedNodeMap* attList = element->getAttributes(); @@ -434,9 +167,10 @@ XSLTProcessor::copyNode(Node* aSourceNode, ProcessorState* aPs) PRUint32 i = 0; for (i = 0; i < attList->getLength(); i++) { Attr* attr = (Attr*)attList->item(i); - NS_ASSERTION(mResultHandler, "mResultHandler must not be NULL!"); - mResultHandler->attribute(attr->getNodeName(), attr->getNamespaceID(), - attr->getNodeValue()); + NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); + aPs->mResultHandler->attribute(attr->getNodeName(), + attr->getNamespaceID(), + attr->getNodeValue()); } } @@ -447,38 +181,69 @@ XSLTProcessor::copyNode(Node* aSourceNode, ProcessorState* aPs) child = child->getNextSibling(); } - NS_ASSERTION(mResultHandler, "mResultHandler must not be NULL!"); - mResultHandler->endElement(name, nsID); + NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); + aPs->mResultHandler->endElement(name, nsID); break; } case Node::PROCESSING_INSTRUCTION_NODE: { ProcessingInstruction* pi = (ProcessingInstruction*)aSourceNode; - NS_ASSERTION(mResultHandler, "mResultHandler must not be NULL!"); - mResultHandler->processingInstruction(pi->getTarget(), pi->getData()); + NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); + aPs->mResultHandler->processingInstruction(pi->getTarget(), pi->getData()); break; } case Node::TEXT_NODE: case Node::CDATA_SECTION_NODE: { - NS_ASSERTION(mResultHandler, "mResultHandler must not be NULL!"); - mResultHandler->characters(aSourceNode->getNodeValue()); + NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); + aPs->mResultHandler->characters(aSourceNode->getNodeValue()); break; } } } +Document* +txXSLTProcessor::createRTFDocument(txOutputMethod aMethod) +{ +#ifdef TX_EXE + return new Document(); +#else + nsresult rv; + nsCOMPtr domDoc = do_CreateInstance(kXMLDocumentCID, &rv); + NS_ENSURE_SUCCESS(rv, nsnull); + return new Document(domDoc); +#endif +} + void -XSLTProcessor::processAction(Node* aAction, - ProcessorState* aPs) +txXSLTProcessor::logMessage(const String& aMessage) +{ +#ifdef TX_EXE + cout << "xsl:message - "<< aMessage << endl; +#else + nsresult rv; + nsCOMPtr consoleSvc = + do_GetService("@mozilla.org/consoleservice;1", &rv); + NS_ASSERTION(NS_SUCCEEDED(rv), + "xsl:message couldn't get console service"); + if (consoleSvc) { + nsAutoString logString(NS_LITERAL_STRING("xsl:message - ")); + logString.Append(aMessage.getConstNSString()); + rv = consoleSvc->LogStringMessage(logString.get()); + NS_ASSERTION(NS_SUCCEEDED(rv), "xsl:message couldn't log"); + } +#endif +} + +void +txXSLTProcessor::processAction(Node* aAction, + ProcessorState* aPs) { nsresult rv = NS_OK; NS_ASSERTION(aAction, "We need an action to process."); if (!aAction) return; - Document* resultDoc = aPs->getResultDocument(); - unsigned short nodeType = aAction->getNodeType(); // Handle text nodes @@ -487,8 +252,8 @@ XSLTProcessor::processAction(Node* aAction, const String& textValue = aAction->getNodeValue(); if (!XMLUtils::isWhitespace(textValue) || XMLUtils::getXMLSpacePreserve(aAction)) { - NS_ASSERTION(mResultHandler, "mResultHandler must not be NULL!"); - mResultHandler->characters(textValue); + NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); + aPs->mResultHandler->characters(textValue); } return; } @@ -504,7 +269,8 @@ XSLTProcessor::processAction(Node* aAction, // Literal result element // XXX TODO Check for excluded namespaces and aliased namespaces (element and attributes) const String& nodeName = aAction->getNodeName(); - startElement(nodeName, nsID, aPs); + NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); + aPs->mResultHandler->startElement(nodeName, nsID); processAttributeSets(actionElement, aPs); @@ -521,15 +287,15 @@ XSLTProcessor::processAction(Node* aAction, // Process Attribute Value Templates String value; aPs->processAttrValueTemplate(attr->getNodeValue(), actionElement, value); - NS_ASSERTION(mResultHandler, "mResultHandler must not be NULL!"); - mResultHandler->attribute(attr->getNodeName(), attr->getNamespaceID(), value); + NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); + aPs->mResultHandler->attribute(attr->getNodeName(), attr->getNamespaceID(), value); } } // Process children processChildren(actionElement, aPs); - NS_ASSERTION(mResultHandler, "mResultHandler must not be NULL!"); - mResultHandler->endElement(nodeName, nsID); + NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); + aPs->mResultHandler->endElement(nodeName, nsID); return; } @@ -563,7 +329,7 @@ XSLTProcessor::processAction(Node* aAction, expr = aPs->getExpr(actionElement, ProcessorState::SelectAttr); else - expr = mNodeExpr; + expr = gNodeExpr; if (!expr) { TX_RELEASE_ATOM(localName); @@ -580,6 +346,7 @@ XSLTProcessor::processAction(Node* aAction, NodeSet* nodeSet = (NodeSet*)exprResult; if (nodeSet->isEmpty()) { delete nodeSet; + TX_RELEASE_ATOM(localName); return; } @@ -683,7 +450,7 @@ XSLTProcessor::processAction(Node* aAction, String nsURI; aPs->processAttrValueTemplate(resultNs, actionElement, nsURI); - resultNsID = resultDoc->namespaceURIToID(nsURI); + resultNsID = aPs->getStylesheetDocument()->namespaceURIToID(nsURI); } else { String prefix; @@ -709,8 +476,8 @@ XSLTProcessor::processAction(Node* aAction, String value; processChildrenAsValue(actionElement, aPs, MB_TRUE, value); - NS_ASSERTION(mResultHandler, "mResultHandler must not be NULL!"); - mResultHandler->attribute(name, resultNsID, value); + NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); + aPs->mResultHandler->attribute(name, resultNsID, value); } // xsl:call-template else if (localName == txXSLTAtoms::callTemplate) { @@ -790,8 +557,8 @@ XSLTProcessor::processAction(Node* aAction, ++length; } } - NS_ASSERTION(mResultHandler, "mResultHandler must not be NULL!"); - mResultHandler->comment(value); + NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); + aPs->mResultHandler->comment(value); } // xsl:copy else if (localName == txXSLTAtoms::copy) { @@ -846,7 +613,7 @@ XSLTProcessor::processAction(Node* aAction, if (nsURI.isEmpty()) resultNsID = kNameSpaceID_None; else - resultNsID = resultDoc->namespaceURIToID(nsURI); + resultNsID = aPs->getStylesheetDocument()->namespaceURIToID(nsURI); } else { String prefix; @@ -867,11 +634,12 @@ XSLTProcessor::processAction(Node* aAction, return; } - startElement(name, resultNsID, aPs); + NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); + aPs->mResultHandler->startElement(name, resultNsID); processAttributeSets(actionElement, aPs); processChildren(actionElement, aPs); - NS_ASSERTION(mResultHandler, "mResultHandler must not be NULL!"); - mResultHandler->endElement(name, resultNsID); + NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); + aPs->mResultHandler->endElement(name, resultNsID); } // xsl:for-each else if (localName == txXSLTAtoms::forEach) { @@ -891,6 +659,7 @@ XSLTProcessor::processAction(Node* aAction, NodeSet* nodeSet = (NodeSet*)exprResult; if (nodeSet->isEmpty()) { delete nodeSet; + TX_RELEASE_ATOM(localName); return; } txNodeSetContext evalContext(nodeSet, aPs); @@ -968,27 +737,15 @@ XSLTProcessor::processAction(Node* aAction, String message; processChildrenAsValue(actionElement, aPs, MB_FALSE, message); // We should add a MessageObserver class -#ifdef TX_EXE - cout << "xsl:message - "<< message << endl; -#else - nsCOMPtr consoleSvc = - do_GetService("@mozilla.org/consoleservice;1", &rv); - NS_ASSERTION(NS_SUCCEEDED(rv), "xsl:message couldn't get console service"); - if (consoleSvc) { - nsAutoString logString(NS_LITERAL_STRING("xsl:message - ")); - logString.Append(message); - rv = consoleSvc->LogStringMessage(logString.get()); - NS_ASSERTION(NS_SUCCEEDED(rv), "xsl:message couldn't log"); - } -#endif + logMessage(message); } // xsl:number else if (localName == txXSLTAtoms::number) { String result; // XXX ErrorReport, propagate result from ::createNumber txXSLTNumber::createNumber(actionElement, aPs, result); - NS_ASSERTION(mResultHandler, "mResultHandler must not be NULL!"); - mResultHandler->characters(result); + NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); + aPs->mResultHandler->characters(result); } // xsl:param else if (localName == txXSLTAtoms::param) { @@ -1024,8 +781,8 @@ XSLTProcessor::processAction(Node* aAction, String value; processChildrenAsValue(actionElement, aPs, MB_TRUE, value); XMLUtils::normalizePIValue(value); - NS_ASSERTION(mResultHandler, "mResultHandler must not be NULL!"); - mResultHandler->processingInstruction(name, value); + NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); + aPs->mResultHandler->processingInstruction(name, value); } // xsl:sort else if (localName == txXSLTAtoms::sort) { @@ -1036,19 +793,21 @@ XSLTProcessor::processAction(Node* aAction, String data; XMLDOMUtils::getNodeValue(actionElement, data); - NS_ASSERTION(mResultHandler, "mResultHandler must not be NULL!"); -#ifdef TX_EXE - String aValue; - if ((mResultHandler == mOutputHandler) && - actionElement->getAttr(txXSLTAtoms::disableOutputEscaping, - kNameSpaceID_None, aValue) && - aValue.isEqual(YES_VALUE)) - mOutputHandler->charactersNoOutputEscaping(data); - else - mResultHandler->characters(data); -#else - mResultHandler->characters(data); -#endif + NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); + MBool doe = MB_FALSE; + if ((aPs->mResultHandler == aPs->mOutputHandler) && + aPs->mOutputHandler->hasDisableOutputEscaping()) { + String attValue; + doe = actionElement->getAttr(txXSLTAtoms::disableOutputEscaping, + kNameSpaceID_None, attValue) && + attValue.isEqual(YES_VALUE); + } + if (doe) { + aPs->mOutputHandler->charactersNoOutputEscaping(data); + } + else { + aPs->mResultHandler->characters(data); + } } // xsl:value-of else if (localName == txXSLTAtoms::valueOf) { @@ -1068,19 +827,21 @@ XSLTProcessor::processAction(Node* aAction, } exprResult->stringValue(value); - NS_ASSERTION(mResultHandler, "mResultHandler must not be NULL!"); -#ifdef TX_EXE - String aValue; - if ((mResultHandler == mOutputHandler) && - actionElement->getAttr(txXSLTAtoms::disableOutputEscaping, - kNameSpaceID_None, aValue) && - aValue.isEqual(YES_VALUE)) - mOutputHandler->charactersNoOutputEscaping(value); - else - mResultHandler->characters(value); -#else - mResultHandler->characters(value); -#endif + NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); + MBool doe = MB_FALSE; + if ((aPs->mResultHandler == aPs->mOutputHandler) && + aPs->mOutputHandler->hasDisableOutputEscaping()) { + String attValue; + doe = actionElement->getAttr(txXSLTAtoms::disableOutputEscaping, + kNameSpaceID_None, attValue) && + attValue.isEqual(YES_VALUE); + } + if (doe) { + aPs->mOutputHandler->charactersNoOutputEscaping(value); + } + else { + aPs->mResultHandler->characters(value); + } delete exprResult; } // xsl:variable @@ -1114,9 +875,9 @@ XSLTProcessor::processAction(Node* aAction, } void -XSLTProcessor::processAttributeSets(Element* aElement, - ProcessorState* aPs, - Stack* aRecursionStack) +txXSLTProcessor::processAttributeSets(Element* aElement, + ProcessorState* aPs, + Stack* aRecursionStack) { nsresult rv = NS_OK; String names; @@ -1181,8 +942,8 @@ XSLTProcessor::processAttributeSets(Element* aElement, } void -XSLTProcessor::processChildren(Element* aElement, - ProcessorState* aPs) +txXSLTProcessor::processChildren(Element* aElement, + ProcessorState* aPs) { NS_ASSERTION(aElement, "missing aElement"); @@ -1198,32 +959,32 @@ XSLTProcessor::processChildren(Element* aElement, } void -XSLTProcessor::processChildrenAsValue(Element* aElement, - ProcessorState* aPs, - MBool aOnlyText, - String& aValue) +txXSLTProcessor::processChildrenAsValue(Element* aElement, + ProcessorState* aPs, + MBool aOnlyText, + String& aValue) { - txXMLEventHandler* previousHandler = mResultHandler; + txXMLEventHandler* previousHandler = aPs->mResultHandler; txTextHandler valueHandler(aValue, aOnlyText); - mResultHandler = &valueHandler; + aPs->mResultHandler = &valueHandler; processChildren(aElement, aPs); - mResultHandler = previousHandler; + aPs->mResultHandler = previousHandler; } void -XSLTProcessor::processDefaultTemplate(ProcessorState* aPs, - const txExpandedName& aMode) +txXSLTProcessor::processDefaultTemplate(ProcessorState* aPs, + const txExpandedName& aMode) { Node* node = aPs->getEvalContext()->getContextNode(); - switch(node->getNodeType()) + switch (node->getNodeType()) { case Node::ELEMENT_NODE : case Node::DOCUMENT_NODE : { - if (!mNodeExpr) + if (!gNodeExpr) break; - ExprResult* exprResult = mNodeExpr->evaluate(aPs->getEvalContext()); + ExprResult* exprResult = gNodeExpr->evaluate(aPs->getEvalContext()); if (!exprResult || exprResult->getResultType() != ExprResult::NODESET) { String err("None-nodeset returned while processing default template"); @@ -1256,8 +1017,8 @@ XSLTProcessor::processDefaultTemplate(ProcessorState* aPs, case Node::TEXT_NODE : case Node::CDATA_SECTION_NODE : { - NS_ASSERTION(mResultHandler, "mResultHandler must not be NULL!"); - mResultHandler->characters(node->getNodeValue()); + NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); + aPs->mResultHandler->characters(node->getNodeValue()); break; } default: @@ -1268,9 +1029,9 @@ XSLTProcessor::processDefaultTemplate(ProcessorState* aPs, } void -XSLTProcessor::processInclude(String& aHref, - txListIterator* aImportFrame, - ProcessorState* aPs) +txXSLTProcessor::processInclude(String& aHref, + txListIterator* aImportFrame, + ProcessorState* aPs) { // make sure the include isn't included yet txStackIterator iter(aPs->getEnteredStylesheets()); @@ -1296,11 +1057,11 @@ XSLTProcessor::processInclude(String& aHref, switch(stylesheet->getNodeType()) { case Node::DOCUMENT_NODE : - processStylesheet((Document*)stylesheet, + processStylesheet((Document*)stylesheet, 0, aImportFrame, aPs); break; case Node::ELEMENT_NODE : - processTopLevel((Element*)stylesheet, + processTopLevel((Element*)stylesheet, 0, aImportFrame, aPs); break; default: @@ -1314,11 +1075,11 @@ XSLTProcessor::processInclude(String& aHref, } void -XSLTProcessor::processMatchedTemplate(Node* aTemplate, - txVariableMap* aParams, - const txExpandedName& aMode, - ProcessorState::ImportFrame* aFrame, - ProcessorState* aPs) +txXSLTProcessor::processMatchedTemplate(Node* aTemplate, + txVariableMap* aParams, + const txExpandedName& aMode, + ProcessorState::ImportFrame* aFrame, + ProcessorState* aPs) { if (aTemplate) { ProcessorState::TemplateRule *oldTemplate, newTemplate; @@ -1338,9 +1099,9 @@ XSLTProcessor::processMatchedTemplate(Node* aTemplate, } nsresult -XSLTProcessor::processParameters(Element* aAction, - txVariableMap* aMap, - ProcessorState* aPs) +txXSLTProcessor::processParameters(Element* aAction, + txVariableMap* aMap, + ProcessorState* aPs) { NS_ASSERTION(aAction && aMap, "missing argument"); nsresult rv = NS_OK; @@ -1388,10 +1149,25 @@ XSLTProcessor::processParameters(Element* aAction, return NS_OK; } +nsresult +txXSLTProcessor::processStylesheet(Document* aStylesheet, + txExpandedNameMap* aGlobalParams, + ProcessorState* aPs) +{ + txListIterator importFrame(aPs->getImportFrames()); + importFrame.addAfter(new ProcessorState::ImportFrame(0)); + if (!importFrame.next()) { + return NS_ERROR_OUT_OF_MEMORY; + } + processStylesheet(aStylesheet, aGlobalParams, &importFrame, aPs); + return NS_OK; +} + void -XSLTProcessor::processStylesheet(Document* aStylesheet, - txListIterator* aImportFrame, - ProcessorState* aPs) +txXSLTProcessor::processStylesheet(Document* aStylesheet, + txExpandedNameMap* aGlobalParams, + txListIterator* aImportFrame, + ProcessorState* aPs) { NS_ASSERTION(aStylesheet, "processTopLevel called without stylesheet"); if (!aStylesheet || !aStylesheet->getDocumentElement()) @@ -1406,7 +1182,7 @@ XSLTProcessor::processStylesheet(Document* aStylesheet, if (((localName == txXSLTAtoms::stylesheet) || (localName == txXSLTAtoms::transform)) && (namespaceID == kNameSpaceID_XSLT)) { - processTopLevel(elem, aImportFrame, aPs); + processTopLevel(elem, aGlobalParams, aImportFrame, aPs); } else { NS_ASSERTION(aImportFrame->current(), "no current importframe"); @@ -1421,9 +1197,9 @@ XSLTProcessor::processStylesheet(Document* aStylesheet, } void -XSLTProcessor::processTemplate(Node* aTemplate, - txVariableMap* aParams, - ProcessorState* aPs) +txXSLTProcessor::processTemplate(Node* aTemplate, + txVariableMap* aParams, + ProcessorState* aPs) { NS_ASSERTION(aTemplate, "aTemplate is NULL"); @@ -1492,14 +1268,27 @@ XSLTProcessor::processTemplate(Node* aTemplate, aPs->setLocalVariables(oldVars); } -void -XSLTProcessor::processTopLevel(Element* aStylesheet, - txListIterator* importFrame, - ProcessorState* aPs) +nsresult +txXSLTProcessor::processTopLevel(Element* aStylesheet, + txExpandedNameMap* aGlobalParams, + ProcessorState* aPs) { - nsresult rv = NS_OK; + txListIterator importFrame(aPs->getImportFrames()); + importFrame.addAfter(new ProcessorState::ImportFrame(0)); + if (!importFrame.next()) { + return NS_ERROR_OUT_OF_MEMORY; + } + processTopLevel(aStylesheet, aGlobalParams, &importFrame, aPs); + return NS_OK; +} - // Index templates and process top level xsl elements +void +txXSLTProcessor::processTopLevel(Element* aStylesheet, + txExpandedNameMap* aGlobalParams, + txListIterator* importFrame, + ProcessorState* aPs) +{ + // Index templates and process top level xslt elements NS_ASSERTION(aStylesheet, "processTopLevel called without stylesheet element"); if (!aStylesheet) return; @@ -1590,11 +1379,28 @@ XSLTProcessor::processTopLevel(Element* aStylesheet, } // xsl:param else if (localName == txXSLTAtoms::param) { - // Once we support stylesheet parameters we should process the - // value here. For now we just use the default value - // See bug 73492 - rv = aPs->addGlobalVariable(element, currentFrame); - if (NS_FAILED(rv)) { + String qName; + element->getAttr(txXSLTAtoms::name, kNameSpaceID_None, qName); + txExpandedName varName; + nsresult rv = varName.init(qName, element, MB_FALSE); + if (NS_SUCCEEDED(rv)) { + ExprResult* defaultValue = 0; + if (aGlobalParams) { + txIGlobalParameter* globalParam = + (txIGlobalParameter*)aGlobalParams->get(varName); + if (globalParam) { + globalParam->getValue(&defaultValue); + } + } + + rv = aPs->addGlobalVariable(varName, element, currentFrame, + defaultValue); + if (NS_FAILED(rv)) { + String err("unable to add global xsl:param"); + aPs->receiveError(err, NS_ERROR_FAILURE); + } + } + else { String err("unable to add global xsl:param"); aPs->receiveError(err, NS_ERROR_FAILURE); } @@ -1725,8 +1531,19 @@ XSLTProcessor::processTopLevel(Element* aStylesheet, } // xsl:variable else if (localName == txXSLTAtoms::variable) { - rv = aPs->addGlobalVariable(element, currentFrame); - if (NS_FAILED(rv)) { + String qName; + element->getAttr(txXSLTAtoms::name, kNameSpaceID_None, qName); + txExpandedName varName; + nsresult rv = varName.init(qName, element, MB_FALSE); + if (NS_SUCCEEDED(rv)) { + rv = aPs->addGlobalVariable(varName, element, currentFrame, + 0); + if (NS_FAILED(rv)) { + String err("unable to add global xsl:variable"); + aPs->receiveError(err, NS_ERROR_FAILURE); + } + } + else { String err("unable to add global xsl:variable"); aPs->receiveError(err, NS_ERROR_FAILURE); } @@ -1769,8 +1586,8 @@ XSLTProcessor::processTopLevel(Element* aStylesheet, } ExprResult* -XSLTProcessor::processVariable(Element* aVariable, - ProcessorState* aPs) +txXSLTProcessor::processVariable(Element* aVariable, + ProcessorState* aPs) { NS_ASSERTION(aVariable, "missing xslVariable"); @@ -1786,592 +1603,58 @@ XSLTProcessor::processVariable(Element* aVariable, if (!rtf) // XXX ErrorReport: Out of memory return 0; - txXMLEventHandler* previousHandler = mResultHandler; - txRtfHandler rtfHandler(aPs->getResultDocument(), rtf); - mResultHandler = &rtfHandler; + txXMLEventHandler* previousHandler = aPs->mResultHandler; + Document* rtfDocument = aPs->getRTFDocument(); + if (!rtfDocument) { + rtfDocument = createRTFDocument(eXMLOutput); + aPs->setRTFDocument(rtfDocument); + } + NS_ASSERTION(rtfDocument, "No document to create result tree fragments"); + if (!rtfDocument) { + return 0; + } + txRtfHandler rtfHandler(rtfDocument, rtf); + aPs->mResultHandler = &rtfHandler; processChildren(aVariable, aPs); - //NS_ASSERTION(previousHandler, "Setting mResultHandler to NULL!"); - mResultHandler = previousHandler; + NS_ASSERTION(previousHandler, "Setting mResultHandler to NULL!"); + aPs->mResultHandler = previousHandler; return rtf; } return new StringResult(); } -#ifdef TX_EXE - -// XXX START -// XXX Standalone only code. This should move to txStandaloneXSLTProcessor -// XXX - -/* - * Processes the given XML Document using the given XSL document - * and returns the result tree - */ -Document* XSLTProcessor::process(Document& xmlDocument, - Document& xslDocument) -{ - Document* result = new Document(); - if (!result) - // XXX ErrorReport: out of memory - return 0; - - /* XXX Disabled for now, need to implement a handler - that creates a result tree. - // Start of block to ensure the destruction of the ProcessorState - // before the destruction of the result document. - { - // Create a new ProcessorState - ProcessorState ps(&aXMLDocument, &aXSLTDocument, &result); - - // Add error observers - txListIterator iter(&errorObservers); - while (iter.hasNext()) - ps.addErrorObserver(*(ErrorObserver*)iter.next()); - - txSingleNodeContext evalContext(&aXMLDocument, &ps); - ps.setEvalContext(&evalContext); - - // Index templates and process top level xsl elements - txListIterator importFrame(ps.getImportFrames()); - importFrame.addAfter(new ProcessorState::ImportFrame(0)); - if (!importFrame.next()) { - delete result; - // XXX ErrorReport: out of memory - return 0; - } - processStylesheet(&aXMLDocument, &aXSLTDocument, &importFrame, &ps); - - initializeHandlers(&ps); - // XXX Set the result document on the handler - - // Process root of XML source document - startTransform(&aXMLDocument, &ps); - } - // End of block to ensure the destruction of the ProcessorState - // before the destruction of the result document. - XXX End of disabled section */ - - // Return result Document - return result; -} - -/* - * Processes the given XML Document using the given XSL document - * and prints the results to the given ostream argument - */ -void XSLTProcessor::process(Document& aXMLDocument, - Node& aStylesheet, - ostream& aOut) -{ - // Need a result document for creating result tree fragments. - Document result; - - // Start of block to ensure the destruction of the ProcessorState - // before the destruction of the result document. - { - // 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(&aXMLDocument, stylesheetDoc, &result); - - // Add error observers - txListIterator iter(&errorObservers); - while (iter.hasNext()) - ps.addErrorObserver(*(ErrorObserver*)iter.next()); - - txSingleNodeContext evalContext(&aXMLDocument, &ps); - ps.setEvalContext(&evalContext); - - // Index templates and process top level xsl elements - txListIterator importFrame(ps.getImportFrames()); - importFrame.addAfter(new ProcessorState::ImportFrame(0)); - if (!importFrame.next()) - // XXX ErrorReport: out of memory - return; - - if (stylesheetElem) - processTopLevel(stylesheetElem, &importFrame, &ps); - else - processStylesheet(stylesheetDoc, &importFrame, &ps); - - initializeHandlers(&ps); - if (mOutputHandler) - mOutputHandler->setOutputStream(&aOut); - - // Process root of XML source document - startTransform(&aXMLDocument, &ps); - } - // End of block to ensure the destruction of the ProcessorState - // before the destruction of the result document. -} - -/** - * Reads an XML Document from the given XML input stream. - * The XSL Stylesheet is obtained from the XML Documents stylesheet PI. - * If no Stylesheet is found, an empty document will be the result; - * otherwise the XML Document is processed using the stylesheet. - * The result tree is printed to the given ostream argument, - * will not close the ostream argument -**/ -void XSLTProcessor::process - (istream& xmlInput, String& xmlFilename, ostream& out) -{ - - XMLParser xmlParser; - Document* xmlDoc = xmlParser.parse(xmlInput, xmlFilename); - if (!xmlDoc) { - String err("error reading XML document: "); - err.append(xmlParser.getErrorString()); - cerr << err << endl; - return; - } - //-- Read in XSL document - String href; - String errMsg; - getHrefFromStylesheetPI(*xmlDoc, href); - istream* xslInput = URIUtils::getInputStream(href,errMsg); - Document* xslDoc = 0; - if ( xslInput ) { - xslDoc = xmlParser.parse(*xslInput, href); - delete xslInput; - } - if (!xslDoc) { - String err("error reading XSL stylesheet document: "); - err.append(xmlParser.getErrorString()); - cerr << err << endl; - delete xmlDoc; - return; - } - - Node* stylesheet; - String frag; - URIUtils::getFragmentIdentifier(href, frag); - if (!frag.isEmpty()) { - stylesheet = xslDoc->getElementById(frag); - if (!stylesheet) { - String err("unable to get fragment"); - cerr << err << endl; - delete xmlDoc; - delete xslDoc; - return; - } - } - else { - stylesheet = xslDoc; - } - - process(*xmlDoc, *stylesheet, out); - delete xmlDoc; - delete xslDoc; -} //-- process - -/** - * Reads an XML Document from the given XML input stream, and - * processes the document using the XSL document derived from - * the given XSL input stream. - * The result tree is printed to the given ostream argument, - * will not close the ostream argument -**/ -void XSLTProcessor::process - (istream& xmlInput, String& xmlFilename, - istream& xslInput, String& xslFilename, - ostream& out) -{ - //-- read in XML Document - XMLParser xmlParser; - Document* xmlDoc = xmlParser.parse(xmlInput, xmlFilename); - if (!xmlDoc) { - String err("error reading XML document: "); - err.append(xmlParser.getErrorString()); - cerr << err << endl; - return; - } - //-- read in XSL Document - Document* xslDoc = xmlParser.parse(xslInput, xslFilename); - if (!xslDoc) { - String err("error reading XSL stylesheet document: "); - err.append(xmlParser.getErrorString()); - cerr << err << endl; - delete xmlDoc; - return; - } - process(*xmlDoc, *xslDoc, out); - delete xmlDoc; - delete xslDoc; -} //-- process - -// XXX -// XXX Standalone only code. This should move to txStandaloneXSLTProcessor -// XXX END - -#endif // ifdef TX_EXE - - //-------------------/ - //- Private Methods -/ -//-------------------/ - -void XSLTProcessor::process(Node* node, - const String& mode, - ProcessorState* ps) { - if (!node) - return; - - ProcessorState::ImportFrame *frame; - txExpandedName nullMode; - Node* xslTemplate = ps->findTemplate(node, nullMode, &frame); - processMatchedTemplate(xslTemplate, 0, nullMode, frame, ps); -} //-- process - -void XSLTProcessor::startTransform(Node* aNode, ProcessorState* aPs) -{ - mHaveDocumentElement = MB_FALSE; - mOutputHandler->startDocument(); - process(aNode, String(), aPs); -#ifdef TX_EXE - txOutputFormat* format = aPs->getOutputFormat(); - if (format->mMethod == eMethodNotSet) { - // This is an unusual case, no output method has been set and we - // didn't create a document element. Switching to XML output mode - // anyway. - txUnknownHandler* oldHandler = (txUnknownHandler*)mOutputHandler; - ostream* out; - oldHandler->getOutputStream(&out); - mOutputHandler = new txXMLOutput(); - format->mMethod = eXMLOutput; - NS_ASSERTION(mOutputHandler, "Setting mResultHandler to NULL!"); - mOutputHandler->setOutputStream(out); - mOutputHandler->setOutputFormat(format); - mResultHandler = mOutputHandler; - oldHandler->flush(mOutputHandler); - delete oldHandler; - } -#endif - mOutputHandler->endDocument(); -} - -MBool XSLTProcessor::initializeHandlers(ProcessorState* aPs) +void +txXSLTProcessor::transform(ProcessorState* aPs) { + nsresult rv = NS_OK; txListIterator frameIter(aPs->getImportFrames()); ProcessorState::ImportFrame* frame; txOutputFormat* outputFormat = aPs->getOutputFormat(); - while ((frame = (ProcessorState::ImportFrame*)frameIter.next())) + while ((frame = (ProcessorState::ImportFrame*)frameIter.next())) { outputFormat->merge(frame->mOutputFormat); - - delete mOutputHandler; -#ifdef TX_EXE - switch (outputFormat->mMethod) { - case eXMLOutput: - { - mOutputHandler = new txXMLOutput(); - break; - } - case eHTMLOutput: - { - mOutputHandler = new txHTMLOutput(); - break; - } - case eTextOutput: - { - mOutputHandler = new txTextOutput(); - break; - } - case eMethodNotSet: - { - mOutputHandler = new txUnknownHandler(); - break; - } - } -#else - switch (outputFormat->mMethod) { - case eMethodNotSet: - case eXMLOutput: - case eHTMLOutput: - { - mOutputHandler = new txMozillaXMLOutput(); - break; - } - case eTextOutput: - { - mOutputHandler = new txMozillaTextOutput(); - break; - } - } -#endif - - mResultHandler = mOutputHandler; - if (!mOutputHandler) - return MB_FALSE; - mOutputHandler->setOutputFormat(outputFormat); - return MB_TRUE; -} - -void -XSLTProcessor::startElement(const String& aName, - const PRInt32 aNsID, - ProcessorState* aPs) -{ - if (!mHaveDocumentElement && (mResultHandler == mOutputHandler)) { - txOutputFormat* format = aPs->getOutputFormat(); - if (format->mMethod == eMethodNotSet) { - // XXX Should check for whitespace-only sibling text nodes - if ((aNsID == kNameSpaceID_None) && - aName.isEqualIgnoreCase(String("html"))) { - // Switch to html output mode according to the XSLT spec. - format->mMethod = eHTMLOutput; -#ifndef TX_EXE - mOutputHandler->setOutputFormat(format); -#endif - } -#ifdef TX_EXE - ostream* out; - mOutputHandler->getOutputStream(&out); - txUnknownHandler* oldHandler = (txUnknownHandler*)mOutputHandler; - if (format->mMethod == eHTMLOutput) { - mOutputHandler = new txHTMLOutput(); - } - else { - mOutputHandler = new txXMLOutput(); - format->mMethod = eXMLOutput; - } - NS_ASSERTION(mOutputHandler, "Setting mResultHandler to NULL!"); - mOutputHandler->setOutputStream(out); - mOutputHandler->setOutputFormat(format); - mResultHandler = mOutputHandler; - oldHandler->flush(mOutputHandler); - delete oldHandler; -#endif - } - mHaveDocumentElement = MB_TRUE; - } - NS_ASSERTION(mResultHandler, "mResultHandler must not be NULL!"); - mResultHandler->startElement(aName, aNsID); -} - -#ifndef TX_EXE - -// XXX START -// XXX Mozilla module only code. This should move to txMozillaXSLTProcessor -// XXX - -NS_IMETHODIMP -XSLTProcessor::TransformDocument(nsIDOMNode* aSourceDOM, - nsIDOMNode* aStyleDOM, - nsIDOMDocument* aOutputDoc, - nsITransformObserver* aObserver) -{ - NS_ENSURE_ARG(aSourceDOM); - NS_ENSURE_ARG(aStyleDOM); - NS_ENSURE_ARG(aOutputDoc); - - if (!URIUtils::CanCallerAccess(aSourceDOM) || - !URIUtils::CanCallerAccess(aStyleDOM) || - !URIUtils::CanCallerAccess(aOutputDoc)) - return NS_ERROR_DOM_SECURITY_ERR; - - // Create wrapper for the source document. - nsCOMPtr 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 styleDOMDocument; - aStyleDOM->GetOwnerDocument(getter_AddRefs(styleDOMDocument)); - if (!styleDOMDocument) - styleDOMDocument = do_QueryInterface(aStyleDOM); - Document xslDocument(styleDOMDocument); - - // Create wrapper for the output document. - nsCOMPtr document = do_QueryInterface(aOutputDoc); - NS_ENSURE_TRUE(document, NS_ERROR_FAILURE); - Document resultDocument(aOutputDoc); - - // Reset the output document. - // Create a temporary channel to get nsIDocument->Reset to - // do the right thing. - nsCOMPtr loadGroup; - nsCOMPtr channel; - nsCOMPtr docURL; - - document->GetDocumentURL(getter_AddRefs(docURL)); - NS_ASSERTION(docURL, "No document URL"); - document->GetDocumentLoadGroup(getter_AddRefs(loadGroup)); - if (!loadGroup) { - nsCOMPtr source = do_QueryInterface(sourceDOMDocument); - if (source) { - source->GetDocumentLoadGroup(getter_AddRefs(loadGroup)); - } } - nsresult rv = NS_NewChannel(getter_AddRefs(channel), docURL, - nsnull, loadGroup); - NS_ENSURE_SUCCESS(rv, rv); - - // Start of hack for keeping the scrollbars on an existing document. - // Based on similar hack that jst wrote for document.open(). - // See bugs 78070 and 55334. - nsCOMPtr root; - document->GetRootContent(getter_AddRefs(root)); - if (root) { - document->SetRootContent(nsnull); - } - - // Call Reset(), this will now do the full reset, except removing - // the root from the document, doing that confuses the scrollbar - // code in mozilla since the document in the root element and all - // the anonymous content (i.e. scrollbar elements) is set to - // null. - rv = document->Reset(channel, loadGroup); - NS_ENSURE_SUCCESS(rv, rv); - - if (root) { - // Tear down the frames for the root element. - document->ContentRemoved(nsnull, root, 0); - } - // End of hack for keeping the scrollbars on an existing document. - - // Start of block to ensure the destruction of the ProcessorState - // before the destruction of the documents. - { - // Create a new ProcessorState - ProcessorState ps(&sourceDocument, &xslDocument, &resultDocument); - - // XXX Need to add error observers - - // Set current txIEvalContext - txSingleNodeContext evalContext(&sourceDocument, &ps); - ps.setEvalContext(&evalContext); - - // Index templates and process top level xsl elements - txListIterator importFrame(ps.getImportFrames()); - importFrame.addAfter(new ProcessorState::ImportFrame(0)); - if (!importFrame.next()) - return NS_ERROR_OUT_OF_MEMORY; - nsCOMPtr styleDoc = do_QueryInterface(aStyleDOM); - if (styleDoc) { - processStylesheet(&xslDocument, &importFrame, &ps); - } - else { - nsCOMPtr 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); - processTopLevel(element, &importFrame, &ps); - } - - initializeHandlers(&ps); - - if (mOutputHandler) { - mOutputHandler->setOutputDocument(aOutputDoc); - } - - // Get the script loader of the result document. - if (aObserver) { - document->GetScriptLoader(getter_AddRefs(mScriptLoader)); - if (mScriptLoader) { - mScriptLoader->AddObserver(this); - } - } - - // Process root of XML source document - startTransform(sourceNode, &ps); - } - // End of block to ensure the destruction of the ProcessorState - // before the destruction of the documents. - - mOutputHandler->getRootContent(getter_AddRefs(root)); - if (root) { - document->ContentInserted(nsnull, root, 0); - } - - mObserver = do_GetWeakReference(aObserver); - SignalTransformEnd(); - - return NS_OK; -} - -NS_IMETHODIMP -XSLTProcessor::ScriptAvailable(nsresult aResult, - nsIDOMHTMLScriptElement *aElement, - PRBool aIsInline, - PRBool aWasPending, - nsIURI *aURI, - PRInt32 aLineNo, - const nsAString& aScript) -{ - if (NS_FAILED(aResult) && mOutputHandler) { - mOutputHandler->removeScriptElement(aElement); - SignalTransformEnd(); - } - - return NS_OK; -} - -NS_IMETHODIMP -XSLTProcessor::ScriptEvaluated(nsresult aResult, - nsIDOMHTMLScriptElement *aElement, - PRBool aIsInline, - PRBool aWasPending) -{ - if (mOutputHandler) { - mOutputHandler->removeScriptElement(aElement); - SignalTransformEnd(); - } - - return NS_OK; -} - -void -XSLTProcessor::SignalTransformEnd() -{ - nsCOMPtr observer = do_QueryReferent(mObserver); - if (!observer) + txIOutputXMLEventHandler* handler = 0; + rv = aPs->mOutputHandlerFactory->createHandlerWith(aPs->getOutputFormat(), + &handler); + if (NS_FAILED(rv)) { return; - - if (!mOutputHandler || !mOutputHandler->isDone()) - return; - - if (mScriptLoader) { - mScriptLoader->RemoveObserver(this); - mScriptLoader = nsnull; } + aPs->mOutputHandler = handler; + aPs->mResultHandler = handler; + aPs->mOutputHandler->startDocument(); - mObserver = nsnull; + frame = 0; + txExpandedName nullMode; + Node* xslTemplate = aPs->findTemplate(aPs->getEvalContext()->getContextNode(), + nullMode, &frame); + processMatchedTemplate(xslTemplate, 0, nullMode, frame, aPs); - // XXX Need a better way to determine transform success/failure - nsCOMPtr rootContent; - mOutputHandler->getRootContent(getter_AddRefs(rootContent)); - nsCOMPtr root = do_QueryInterface(rootContent); - if (root) { - nsCOMPtr resultDoc; - root->GetOwnerDocument(getter_AddRefs(resultDoc)); - observer->OnTransformDone(NS_OK, resultDoc); - } - else { - // XXX Need better error message and code. - observer->OnTransformDone(NS_ERROR_FAILURE, nsnull); - } + aPs->mOutputHandler->endDocument(); } -// XXX -// XXX Mozilla module only code. This should move to txMozillaXSLTProcessor -// XXX END - -#endif - void -XSLTProcessor::xslCopy(Element* aAction, ProcessorState* aPs) +txXSLTProcessor::xslCopy(Element* aAction, ProcessorState* aPs) { Node* node = aPs->getEvalContext()->getContextNode(); @@ -2388,12 +1671,13 @@ XSLTProcessor::xslCopy(Element* aAction, ProcessorState* aPs) String nodeName = element->getNodeName(); PRInt32 nsID = element->getNamespaceID(); - startElement(nodeName, nsID, aPs); + NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); + aPs->mResultHandler->startElement(nodeName, nsID); // XXX copy namespace attributes once we have them processAttributeSets(aAction, aPs); processChildren(aAction, aPs); - NS_ASSERTION(mResultHandler, "mResultHandler must not be NULL!"); - mResultHandler->endElement(nodeName, nsID); + NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); + aPs->mResultHandler->endElement(nodeName, nsID); break; } default: @@ -2404,7 +1688,7 @@ XSLTProcessor::xslCopy(Element* aAction, ProcessorState* aPs) } void -XSLTProcessor::xslCopyOf(ExprResult* aExprResult, ProcessorState* aPs) +txXSLTProcessor::xslCopyOf(ExprResult* aExprResult, ProcessorState* aPs) { if (!aExprResult) return; @@ -2424,8 +1708,8 @@ XSLTProcessor::xslCopyOf(ExprResult* aExprResult, ProcessorState* aPs) { String value; aExprResult->stringValue(value); - NS_ASSERTION(mResultHandler, "mResultHandler must not be NULL!"); - mResultHandler->characters(value); + NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); + aPs->mResultHandler->characters(value); } } } diff --git a/mozilla/extensions/transformiix/source/xslt/XSLTProcessor.h b/mozilla/extensions/transformiix/source/xslt/XSLTProcessor.h index f03bb092de6..e26842f1db6 100644 --- a/mozilla/extensions/transformiix/source/xslt/XSLTProcessor.h +++ b/mozilla/extensions/transformiix/source/xslt/XSLTProcessor.h @@ -28,354 +28,247 @@ #ifndef TRANSFRMX_XSLTPROCESSOR_H #define TRANSFRMX_XSLTPROCESSOR_H -#ifndef __BORLANDC__ -#ifdef TX_EXE -#include -#include -#endif -#endif - - -#ifndef TX_EXE -#include "nsICSSStyleSheet.h" -#include "nsICSSLoaderObserver.h" -#include "nsIDocumentTransformer.h" -#include "nsIDOMHTMLScriptElement.h" -#include "nsIScriptLoader.h" -#include "nsIScriptLoaderObserver.h" -#include "nsITransformObserver.h" -#include "nsWeakPtr.h" -#include "txMozillaTextOutput.h" -#include "txMozillaXMLOutput.h" -#endif - -#include "dom.h" -#include "ExprParser.h" -#include "TxObject.h" -#include "NamedMap.h" #include "ProcessorState.h" -#include "TxString.h" -#include "ErrorObserver.h" -#include "List.h" -#include "txTextHandler.h" -#ifndef TX_EXE -/* 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" - -#else - -/* - * Initialisation and shutdown routines for standalone - * Allocate and free static atoms. - */ -MBool txInit(); -MBool txShutdown(); - -#endif +class txIGlobalParameter : public TxObject +{ +public: + virtual nsresult getValue(ExprResult** aValue) = 0; +}; /** - * A class for Processing XSL Stylesheets -**/ -class XSLTProcessor -#ifndef TX_EXE -: public nsIDocumentTransformer, - public nsIScriptLoaderObserver -#endif + * A class for Processing XSLT Stylesheets + */ +class txXSLTProcessor { - friend class ProcessorState; - public: -#ifndef TX_EXE - // nsISupports interface - NS_DECL_ISUPPORTS - - // nsIDocumentTransformer interface - NS_DECL_NSIDOCUMENTTRANSFORMER - - NS_DECL_NSISCRIPTLOADEROBSERVER -#endif + /** + * Initialisation and shutdown routines + * Allocate and free static atoms. + */ + static MBool txInit(); + static MBool txShutdown(); /** - * A warning message used by all templates that do not allow non character - * data to be generated - **/ - static const String NON_TEXT_TEMPLATE_WARNING; + * Processes a stylesheet document. + * + * @param aStylesheet the stylesheet document to process + * @param aPs the current ProcessorState + */ + static nsresult processStylesheet(Document* aStylesheet, + txExpandedNameMap* aGlobalParams, + ProcessorState* aPs); /** - * Creates a new XSLTProcessor - **/ - XSLTProcessor(); + * Processes a stylesheet element. + * + * @param aStylesheet the stylesheet element to process + * @param aPs the current ProcessorState + */ + static nsresult processTopLevel(Element* aStylesheet, + txExpandedNameMap* aGlobalParams, + ProcessorState* aPs); /** - * Default destructor for XSLTProcessor - **/ - virtual ~XSLTProcessor(); - - /** - * Registers the given ErrorObserver with this XSLTProcessor - **/ - void addErrorObserver(ErrorObserver& errorObserver); - - /** - * Returns the name of this XSLT processor - **/ - String& getAppName(); - - /** - * Returns the version of this XSLT processor - **/ - String& getAppVersion(); - - //--------------------------------------------/ - //-- Methods that return the Result Document -/ - //--------------------------------------------/ -#ifdef TX_EXE - /** - * 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 getHrefFromStylesheetPI(Document& xmlDocument, String& href); - - /** - * Processes the given XML Document, the XSL stylesheet - * will be retrieved from the XML Stylesheet Processing instruction, - * otherwise an empty document will be returned. - * @param xmlDocument the XML document to process - * @return the result tree. - **/ - Document* process(Document& xmlDocument); - -#endif - - /** - * Processes the given XML Document using the given XSL document - * @return the result tree. - * @param documentBase the document base for resolving relative URIs. - **/ - Document* process - (Document& xmlDocument, Document& xslDocument); - - /** - * Reads an XML Document from the given XML input stream, and - * processes the document using the XSL document derived from - * the given XSL input stream. - * @param documentBase the document base for resolving relative URIs. - * @return the result tree. - **/ - Document* process(istream& xmlInput, String& xmlFilename, - istream& xslInput, String& xslFilename); - -#ifdef TX_EXE - /** - * Reads an XML document from the given XML input stream. The - * XML document is processed using the associated XSL document - * retrieved from the XML document's Stylesheet Processing Instruction, - * otherwise an empty document will be returned. - * @param xmlDocument the XML document to process - * @param documentBase the document base of the XML document, for - * resolving relative URIs - * @return the result tree. - **/ - Document* process(istream& xmlInput, String& xmlFilename); - - //----------------------------------------------/ - //-- Methods that print the result to a stream -/ - //----------------------------------------------/ - - /** - * Reads an XML Document from the given XML input stream. - * The XSL Stylesheet is obtained from the XML Documents stylesheet PI. - * If no Stylesheet is found, an empty document will be the result; - * otherwise the XML Document is processed using the stylesheet. - * The result tree is printed to the given ostream argument, - * will not close the ostream argument - **/ - void process(istream& xmlInput, String& xmlFilename, ostream& out); - - /** - * Processes the given XML Document using the given XSL document. - * The result tree is printed to the given ostream argument, - * will not close the ostream argument - * @param documentBase the document base for resolving relative URIs. - **/ - void process(Document& aXMLDocument, Node& aStylesheet, - ostream& aOut); - - /** - * Reads an XML Document from the given XML input stream, and - * processes the document using the XSL document derived from - * the given XSL input stream. - * The result tree is printed to the given ostream argument, - * will not close the ostream argument - * @param documentBase the document base for resolving relative URIs. - **/ - void process(istream& xmlInput, String& xmlFilename, - istream& xslInput, String& xslFilename, - ostream& out); - -#endif + * Transforms a node. + * + * @param aPs the current ProcessorState with the node + * as current node and the desired templates + */ + static void transform(ProcessorState* aPs); private: - - /** - * Application Name and version - **/ - String appName; - String appVersion; - - /** - * The list of ErrorObservers - **/ - List errorObservers; - - /** - * Fatal ErrorObserver - **/ - SimpleErrorObserver fatalObserver; - - /** - * The version of XSL which this Processes - **/ - String xslVersion; - - /* - * Used as default expression for some elements - */ - Expr* mNodeExpr; - -#ifdef TX_EXE - /** - * Parses the contents of data, and returns the type and href psuedo attributes - **/ - void parseStylesheetPI(String& data, String& type, String& href); -#endif - - void process(Node* node, - const String& mode, - ProcessorState* ps); - - /* * Copy a node. For document nodes, copy the children. + * + * @param aSourceNode node to copy + * @param aPs the current ProcessorState */ - void copyNode(Node* aNode, ProcessorState* aPs); - - void processAction(Node* aAction, ProcessorState* aPs); + static void copyNode(Node* aSourceNode, ProcessorState* aPs); /** - * Processes the attribute sets specified in the use-attribute-sets attribute - * of the element specified in aElement - **/ - void processAttributeSets(Element* aElement, ProcessorState* aPs, - Stack* aRecursionStack = 0); - - /** - * Processes the children of the specified element using the given context node - * and ProcessorState - * @param aElement template to be processed. Must be != NULL - * @param aPs current ProcessorState - **/ - void processChildren(Element* aElement, - ProcessorState* aPs); - - void processChildrenAsValue(Element* aElement, - ProcessorState* aPs, - MBool aOnlyText, - String& aValue); - - /** - * Invokes the default template for the specified node - * @param aPs current ProcessorState - * @param aMode template mode - **/ - void processDefaultTemplate(ProcessorState* aPs, - const txExpandedName& aMode); - - /* - * Processes an include or import stylesheet - * @param aHref URI of stylesheet to process - * @param aImportFrame current importFrame iterator - * @param aPs current ProcessorState + * Create the document we will use to create result tree fragments. + * + * @param aMethod the output method indicating which type of + * document to create + * @returns a document to create RTF nodes */ - void processInclude(String& aHref, - txListIterator* aImportFrame, - ProcessorState* aPs); + static Document* createRTFDocument(txOutputMethod aMethod); - void processMatchedTemplate(Node* aTemplate, - txVariableMap* aParams, - const txExpandedName& aMode, - ProcessorState::ImportFrame* aFrame, + /** + * Log a message. + * + * @param aMessage the message to log + */ + static void logMessage(const String& aMessage); + + /** + * Instantiate aAction in the result tree. + * Either perform the action associated with the element in the + * XSLT namespace, or copy the element as literal result element. + * + * @param aAction literal result element or XSLT element + * @param aPs the current ProcessorState + */ + static void processAction(Node* aAction, + ProcessorState* aPs); + + /** + * Processes the attribute sets specified in the use-attribute-sets + * attribute of the element specified in aElement. + * + * @param aElement Element specifying the attribute sets + * @param aPs the current ProcessorState + * @param aRecursionStack recursion stack to track attribute sets + * including themselves, even indirectly + */ + static void processAttributeSets(Element* aElement, ProcessorState* aPs, + Stack* aRecursionStack = 0); + + /** + * Processes the children of the specified element using the given + * context node and ProcessorState. + * + * @param aElement the template to be processed. Must be != NULL + * @param aPs the current ProcessorState + */ + static void processChildren(Element* aElement, ProcessorState* aPs); - /* + /** + * Processes the children of the specified element using the given + * context node and ProcessorState and append the text data to + * aValue. + * + * @param aElement the template to be processed. Must be != NULL + * @param aPs the current ProcessorState + * @param aOnlyText if true, don't allow for nested content + * @param aValue String reference to append the result to + */ + static void processChildrenAsValue(Element* aElement, + ProcessorState* aPs, + MBool aOnlyText, + String& aValue); + + /** + * Invokes the default template for the specified node. + * + * @param aPs the current ProcessorState + * @param aMode template mode + */ + static void processDefaultTemplate(ProcessorState* aPs, + const txExpandedName& aMode); + + /** + * Processes an include or import stylesheet. + * + * @param aHref URI of stylesheet to process + * @param aImportFrame current importFrame iterator + * @param aPs the current ProcessorState + */ + static void processInclude(String& aHref, + txListIterator* aImportFrame, + ProcessorState* aPs); + + /** + * Instantiate the children of the template aTemplate with the + * parameters aParams and the mode aMode. + * + * @param aTemplate xsl:template to instantiate + * @param aParams txVariableMap holding the params, if given + * @param aMode mode of this template + * @param aFrame the current import frame, needed for apply-templates + * @param aPs the current ProcessorState + */ + static void processMatchedTemplate(Node* aTemplate, + txVariableMap* aParams, + const txExpandedName& aMode, + ProcessorState::ImportFrame* aFrame, + ProcessorState* aPs); + + /** * Processes the xsl:with-param child elements of the given xsl action. + * * @param aAction the action node that takes parameters (xsl:call-template - * or xsl:apply-templates + * or xsl:apply-templates) * @param aMap map to place parsed variables in * @param aPs the current ProcessorState * @return errorcode */ - nsresult processParameters(Element* aAction, txVariableMap* aMap, - ProcessorState* aPs); + static nsresult processParameters(Element* aAction, txVariableMap* aMap, + ProcessorState* aPs); - void processStylesheet(Document* aStylesheet, - txListIterator* aImportFrame, - ProcessorState* aPs); + /** + * Add a stylesheet to the processorstate. If the document element + * is a LRE, just add one template with pattern "/". Otherwise, + * call processTopLevel with the document element. + * + * @param aStylesheet the document to be added to the ps + * @param aImportFrame the import frame to add the stylesheet to + * @param aPs the current ProcessorState + */ + static void processStylesheet(Document* aStylesheet, + txExpandedNameMap* aGlobalParams, + txListIterator* aImportFrame, + ProcessorState* aPs); - /* + /** * Processes the specified template using the given context, - * ProcessorState, and parameters. - * @param aTemplate the node in the xslt document that contains the - * template - * @param aParams map with parameters to the template - * @param aPs the current ProcessorState + * ProcessorState, and parameters. Iterates through the + * |xsl:param|s and then calls processAction. + * + * @param aTemplate xsl:template to process + * @param aParams variable map with xsl:with-param values + * @param aPs the current ProcessorState */ - void processTemplate(Node* aTemplate, txVariableMap* aParams, - ProcessorState* aPs); + static void processTemplate(Node* aTemplate, txVariableMap* aParams, + ProcessorState* aPs); - void processTopLevel(Element* aStylesheet, - txListIterator* importFrame, - ProcessorState* aPs); - - ExprResult* processVariable(Element* aVariable, ProcessorState* aPs); - - void startTransform(Node* aNode, ProcessorState* aPs); - - MBool initializeHandlers(ProcessorState* aPs); - - /* - * Performs the xsl:copy action as specified in the XSLT specification + /** + * Processes the top-level children of xsl:stylesheet. + * + * @param aStylesheet the stylesheet + * @param aImportFrame the import frame of the stylesheet + * @param aPs the current ProcessorState */ - void xslCopy(Element* aAction, ProcessorState* aPs); + static void processTopLevel(Element* aStylesheet, + txExpandedNameMap* aGlobalParams, + txListIterator* aImportFrame, + ProcessorState* aPs); - /* - * Performs the xsl:copy-of action as specified in the XSLT specification + /** + * Processes the given xsl:variable. + * + * @param aVariable the variable element + * @param aPs the current ProcessorState */ - void xslCopyOf(ExprResult* aExprResult, ProcessorState* aPs); + static ExprResult* processVariable(Element* aVariable, + ProcessorState* aPs); - void startElement(const String& aName, const PRInt32 aNsID, ProcessorState* aPs); + /** + * Performs the xsl:copy action as specified in the XSLT specification. + * + * @param aAction element to copy + * @param aPs the current ProcessorState + */ + static void xslCopy(Element* aAction, + ProcessorState* aPs); -#ifdef TX_EXE - txStreamXMLEventHandler* mOutputHandler; -#else - txMozillaXMLEventHandler* mOutputHandler; -#endif - txXMLEventHandler* mResultHandler; - MBool mHaveDocumentElement; -#ifndef TX_EXE - void SignalTransformEnd(); + /** + * Performs the xsl:copy-of action as specified in the XSLT specification. + * + * @param aExprResult expression result to copy + * @param aPs the current ProcessorState + */ + static void xslCopyOf(ExprResult* aExprResult, + ProcessorState* aPs); - nsCOMPtr mScriptLoader; - nsWeakPtr mObserver; -#endif -}; //-- XSLTProcessor + /** + * Used as default expression for some elements + */ + static Expr* gNodeExpr; + + friend class ProcessorState; +}; #endif diff --git a/mozilla/extensions/transformiix/source/xslt/txHTMLOutput.cpp b/mozilla/extensions/transformiix/source/xslt/txHTMLOutput.cpp index a59b27dc47b..efe7ae09c5b 100644 --- a/mozilla/extensions/transformiix/source/xslt/txHTMLOutput.cpp +++ b/mozilla/extensions/transformiix/source/xslt/txHTMLOutput.cpp @@ -41,7 +41,8 @@ #include "txOutputFormat.h" #include "XMLUtils.h" -txHTMLOutput::txHTMLOutput() +txHTMLOutput::txHTMLOutput(txOutputFormat* aFormat, ostream* aOut) + : txXMLOutput(aFormat, aOut) { mUseEmptyElementShorthand = MB_FALSE; diff --git a/mozilla/extensions/transformiix/source/xslt/txHTMLOutput.h b/mozilla/extensions/transformiix/source/xslt/txHTMLOutput.h index d16a435fc18..ebdc476c578 100644 --- a/mozilla/extensions/transformiix/source/xslt/txHTMLOutput.h +++ b/mozilla/extensions/transformiix/source/xslt/txHTMLOutput.h @@ -46,7 +46,7 @@ class txHTMLOutput : public txXMLOutput { public: - txHTMLOutput(); + txHTMLOutput(txOutputFormat* aFormat, ostream* aOut); ~txHTMLOutput(); /* diff --git a/mozilla/extensions/transformiix/source/xslt/txMozillaTextOutput.cpp b/mozilla/extensions/transformiix/source/xslt/txMozillaTextOutput.cpp index 19735c205ef..7d376e1ec50 100644 --- a/mozilla/extensions/transformiix/source/xslt/txMozillaTextOutput.cpp +++ b/mozilla/extensions/transformiix/source/xslt/txMozillaTextOutput.cpp @@ -37,21 +37,58 @@ * ***** END LICENSE BLOCK ***** */ #include "txMozillaTextOutput.h" +#include "nsContentCID.h" #include "nsIDocument.h" #include "nsIDOMDocument.h" #include "nsIDOMElement.h" #include "nsIDOMHTMLElement.h" #include "nsIDOMText.h" +#include "nsIDocumentTransformer.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 doc; + aDest->GetOwnerDocument(getter_AddRefs(doc)); + NS_ASSERTION(doc, "unable to get ownerdocument"); + nsCOMPtr textNode; + nsresult rv = doc->CreateTextNode(NS_LITERAL_STRING(""), + getter_AddRefs(textNode)); + if (NS_FAILED(rv)) { + return; + } + nsCOMPtr dummy; + rv = aDest->AppendChild(textNode, getter_AddRefs(dummy)); + if (NS_FAILED(rv)) { + return; + } + + mTextNode = textNode; + return; } txMozillaTextOutput::~txMozillaTextOutput() { } +NS_IMPL_ISUPPORTS1(txMozillaTextOutput, txIOutputXMLEventHandler); + void txMozillaTextOutput::attribute(const String& aName, const PRInt32 aNsID, const String& aValue) @@ -68,12 +105,12 @@ void txMozillaTextOutput::comment(const String& aData) { } -void txMozillaTextOutput::disableStylesheetLoad() -{ -} - void txMozillaTextOutput::endDocument() { + nsCOMPtr observer = do_QueryReferent(mObserver); + if (observer) { + observer->OnTransformDone(NS_OK, mDocument); + } } void txMozillaTextOutput::endElement(const String& aName, @@ -81,36 +118,20 @@ 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, 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!"); - if (!aDocument) - return; - + nsresult rv = NS_OK; + /* * Create an XHTML document to hold the text. * @@ -120,92 +141,172 @@ void txMozillaTextOutput::setOutputDocument(nsIDOMDocument* aDocument) *
 * The text comes here * 
* * + * + * Except if we are transforming into a non-displayed document we create + * the following DOM + * + * * The text comes here * */ + + nsCOMPtr doc; + 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 nsDoc = do_QueryInterface(mDocument); + if (nsDoc) { + nsDoc->SetTitle(NS_LITERAL_STRING("")); + } + + // Reset and set up document + nsCOMPtr loadGroup; + nsCOMPtr channel; + nsCOMPtr sourceDoc = do_QueryInterface(aSourceDocument); + sourceDoc->GetDocumentLoadGroup(getter_AddRefs(loadGroup)); + nsCOMPtr 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 docURL; + sourceDoc->GetDocumentURL(getter_AddRefs(docURL)); + serv->NewChannelFromURI(docURL, getter_AddRefs(channel)); + } + doc->Reset(channel, loadGroup); + nsCOMPtr 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 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 textContainer; + if (!aResultDocument && !observer) { + nsCOMPtr 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 element, docElement; + nsCOMPtr 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 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 htmlElement = do_QueryInterface(pre); + htmlElement->SetId(NS_LITERAL_STRING("transformiixResult")); + NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to append the id"); + + textContainer = pre; + } - nsCOMPtr element, docElement; - nsCOMPtr parent, pre; nsCOMPtr textNode; - - 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 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 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(""), + mDocument->CreateTextNode(NS_LITERAL_STRING(""), getter_AddRefs(textNode)); NS_ASSERTION(textNode, "Failed to create the text node"); if (!textNode) { return; } - rv = pre->AppendChild(textNode, getter_AddRefs(parent)); + nsCOMPtr dummy; + rv = textContainer->AppendChild(textNode, getter_AddRefs(dummy)); NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to append the text node"); if (NS_FAILED(rv)) { return; @@ -214,18 +315,13 @@ void txMozillaTextOutput::setOutputDocument(nsIDOMDocument* aDocument) mTextNode = textNode; } -void txMozillaTextOutput::setOutputFormat(txOutputFormat* aOutputFormat) -{ - mOutputFormat.reset(); - mOutputFormat.merge(*aOutputFormat); - mOutputFormat.setFromDefaults(); -} - -void txMozillaTextOutput::startDocument() -{ -} - void txMozillaTextOutput::startElement(const String& aName, const PRInt32 aNsID) { } + +void txMozillaTextOutput::getOutputDocument(nsIDOMDocument** aDocument) +{ + *aDocument = mDocument; + NS_IF_ADDREF(*aDocument); +} diff --git a/mozilla/extensions/transformiix/source/xslt/txMozillaTextOutput.h b/mozilla/extensions/transformiix/source/xslt/txMozillaTextOutput.h index a582fca3672..81e3e3cfa1e 100644 --- a/mozilla/extensions/transformiix/source/xslt/txMozillaTextOutput.h +++ b/mozilla/extensions/transformiix/source/xslt/txMozillaTextOutput.h @@ -43,14 +43,24 @@ #include "nsIContent.h" #include "nsIDOMCharacterData.h" #include "nsCOMPtr.h" +#include "nsWeakPtr.h" #include "txOutputFormat.h" +#include "nsIDOMDocument.h" +#include "nsIDOMDocumentFragment.h" -class txMozillaTextOutput : public txMozillaXMLEventHandler +class nsITransformObserver; + +class txMozillaTextOutput : public txIOutputXMLEventHandler { public: - txMozillaTextOutput(); + txMozillaTextOutput(nsIDOMDocument* aSourceDocument, + nsIDOMDocument* aResultDocument, + nsITransformObserver* aObserver); + txMozillaTextOutput(nsIDOMDocumentFragment* aDest); virtual ~txMozillaTextOutput(); + NS_DECL_ISUPPORTS + /** * Signals to receive the start of an attribute. * @@ -69,6 +79,16 @@ public: */ 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. * @@ -91,6 +111,18 @@ public: void endElement(const String& aName, 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. * @@ -114,48 +146,19 @@ public: 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 - * still loading. - * - * @param aReturn the script element to remove - */ - void removeScriptElement(nsIDOMHTMLScriptElement *aElement); - - /** - * Sets the Mozilla output document. + * Gets the Mozilla output document * * @param aDocument the Mozilla output document */ - void setOutputDocument(nsIDOMDocument* aDocument); + void getOutputDocument(nsIDOMDocument** aDocument); private: + void createResultDocument(nsIDOMDocument* aSourceDocument, + nsIDOMDocument* aResultDocument); + nsCOMPtr mTextNode; - nsCOMPtr mRootContent; + nsWeakPtr mObserver; + nsCOMPtr mDocument; txOutputFormat mOutputFormat; }; diff --git a/mozilla/extensions/transformiix/source/xslt/txMozillaXMLOutput.cpp b/mozilla/extensions/transformiix/source/xslt/txMozillaXMLOutput.cpp index b8891982412..18221cae6c2 100644 --- a/mozilla/extensions/transformiix/source/xslt/txMozillaXMLOutput.cpp +++ b/mozilla/extensions/transformiix/source/xslt/txMozillaXMLOutput.cpp @@ -39,6 +39,7 @@ #include "txMozillaXMLOutput.h" #include "nsIDocument.h" +#include "nsIDocShell.h" #include "nsIDOMComment.h" #include "nsIDOMDocumentType.h" #include "nsIDOMDOMImplementation.h" @@ -48,31 +49,80 @@ #include "nsIDOMHTMLTableSectionElem.h" #include "nsIDOMHTMLScriptElement.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 "txAtoms.h" -#include "nsIParser.h" -#include "nsNetUtil.h" -#include "nsIScriptGlobalObject.h" -#include "nsIRefreshURI.h" -#include "nsIDocShell.h" +#include "nsIDOMDocumentFragment.h" + +static NS_DEFINE_CID(kXMLDocumentCID, NS_XMLDOCUMENT_CID); +static NS_DEFINE_CID(kHTMLDocumentCID, NS_HTMLDOCUMENT_CID); #define kXHTMLNameSpaceURI "http://www.w3.org/1999/xhtml" -#define kTXNameSpaceURI "http://www.mozilla.org/TransforMiix" -#define kTXWrapper "transformiix:result" #define TX_ENSURE_CURRENTNODE \ NS_ASSERTION(mCurrentNode, "mCurrentNode is NULL"); \ if (!mCurrentNode) \ 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 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() { } +NS_IMPL_ISUPPORTS2(txMozillaXMLOutput, + txIOutputXMLEventHandler, + nsIScriptLoaderObserver); + void txMozillaXMLOutput::attribute(const String& aName, const PRInt32 aNsID, const String& aValue) @@ -118,22 +168,16 @@ void txMozillaXMLOutput::comment(const String& aData) nsresult rv = mDocument->CreateComment(aData, getter_AddRefs(comment)); NS_ASSERTION(NS_SUCCEEDED(rv), "Can't create comment"); - - nsCOMPtr node = do_QueryInterface(comment); nsCOMPtr resultNode; - rv = mCurrentNode->AppendChild(node, getter_AddRefs(resultNode)); + rv = mCurrentNode->AppendChild(comment, getter_AddRefs(resultNode)); NS_ASSERTION(NS_SUCCEEDED(rv), "Can't append comment"); } -void txMozillaXMLOutput::disableStylesheetLoad() -{ - mDisableStylesheetLoad = PR_TRUE; -} - void txMozillaXMLOutput::endDocument() { closePrevious(eCloseElement | eFlushText); - if (!mHaveTitleElement) { + // This should really be handled by nsIDocument::Reset + if (mCreatingNewDocument && !mHaveTitleElement) { nsCOMPtr domDoc = do_QueryInterface(mDocument); if (domDoc) { 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) { + TX_ENSURE_CURRENTNODE; + #ifdef DEBUG nsAutoString 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"); - - *aReturn = mRootContent; - NS_IF_ADDREF(*aReturn); - return NS_OK; -} - -PRBool txMozillaXMLOutput::isDone() -{ - PRUint32 scriptCount = 0; - if (mScriptElements) - mScriptElements->Count(&scriptCount); - return (scriptCount == 0); + *aDocument = mDocument; + NS_IF_ADDREF(*aDocument); } 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, getter_AddRefs(pi)); NS_ASSERTION(NS_SUCCEEDED(rv), "Can't create processing instruction"); + if (NS_FAILED(rv)) + return; - nsCOMPtr ssle = do_QueryInterface(pi); - if (ssle) { - ssle->InitStyleLinkElement(nsnull, PR_FALSE); - ssle->SetEnableUpdates(PR_FALSE); + nsCOMPtr ssle; + if (mCreatingNewDocument) { + ssle = do_QueryInterface(pi); + if (ssle) { + ssle->InitStyleLinkElement(nsnull, PR_FALSE); + ssle->SetEnableUpdates(PR_FALSE); + } } nsCOMPtr resultNode; - mCurrentNode->AppendChild(pi, getter_AddRefs(resultNode)); + rv = mCurrentNode->AppendChild(pi, getter_AddRefs(resultNode)); NS_ASSERTION(NS_SUCCEEDED(rv), "Can't append processing instruction"); if (NS_FAILED(rv)) return; if (ssle) { - ssle->SetEnableUpdates(PR_TRUE); - rv = ssle->UpdateStyleSheet(nsnull, mStyleSheetCount); - if (NS_SUCCEEDED(rv) || (rv == NS_ERROR_HTMLPARSER_BLOCK)) - mStyleSheetCount++; + ssle->SetEnableUpdates(PR_TRUE); + rv = ssle->UpdateStyleSheet(nsnull, mStyleSheetCount); + if (NS_SUCCEEDED(rv) || (rv == NS_ERROR_HTMLPARSER_BLOCK)) { + 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 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() { - NS_ASSERTION(mDocument, "Document can't be NULL!"); + mInTransform = PR_TRUE; } void txMozillaXMLOutput::startElement(const String& aName, const PRInt32 aNsID) { + TX_ENSURE_CURRENTNODE; + closePrevious(eCloseElement | eFlushText); nsresult rv; - if (!mRootContent && !mOutputFormat.mSystemId.isEmpty()) { - // No root element yet, so add the doctype if necesary. - nsCOMPtr implementation; - rv = mDocument->GetImplementation(getter_AddRefs(implementation)); - NS_ASSERTION(NS_SUCCEEDED(rv), "Can't get DOMImplementation"); - if (NS_SUCCEEDED(rv)) { - nsAutoString qName; - nsCOMPtr documentType; - nsCOMPtr 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 element; mDontAddCurrent = PR_FALSE; if ((mOutputFormat.mMethod == eHTMLOutput) && (aNsID == kNameSpaceID_None)) { - // Outputting HTML as XHTML, lowercase element names - nsAutoString lowerName(aName); - ToLowerCase(lowerName); - rv = mDocument->CreateElementNS(NS_LITERAL_STRING(kXHTMLNameSpaceURI), lowerName, - getter_AddRefs(element)); - NS_ASSERTION(NS_SUCCEEDED(rv), "Can't create element"); + rv = mDocument->CreateElement(aName, + getter_AddRefs(element)); + if (NS_FAILED(rv)) { + return; + } startHTMLElement(element); } else { nsAutoString 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"); + if (NS_FAILED(rv)) { + return; + } if (aNsID == kNameSpaceID_XHTML) startHTMLElement(element); } - if (element) { + if (mCreatingNewDocument) { nsCOMPtr cont = do_QueryInterface(element); - if (cont) { - nsCOMPtr doc = do_QueryInterface(mDocument); - cont->SetDocument(doc, PR_FALSE, PR_TRUE); - } - mParentNode = mCurrentNode; - mCurrentNode = do_QueryInterface(element); + NS_ASSERTION(cont, "element doesn't implement nsIContent"); + nsCOMPtr doc = do_QueryInterface(mDocument); + cont->SetDocument(doc, PR_FALSE, PR_TRUE); } + mParentNode = mCurrentNode; + mCurrentNode = do_QueryInterface(element); } void txMozillaXMLOutput::closePrevious(PRInt8 aAction) @@ -367,11 +363,6 @@ void txMozillaXMLOutput::closePrevious(PRInt8 aAction) TX_ENSURE_CURRENTNODE; nsresult rv; - PRInt32 namespaceID = kNameSpaceID_None; - nsCOMPtr currentContent = do_QueryInterface(mCurrentNode); - if (currentContent) - currentContent->GetNameSpaceID(namespaceID); - if ((aAction & eCloseElement) && mParentNode) { nsCOMPtr document = do_QueryInterface(mParentNode); nsCOMPtr currentElement = do_QueryInterface(mCurrentNode); @@ -446,16 +437,18 @@ void txMozillaXMLOutput::startHTMLElement(nsIDOMElement* aElement) mDontAddCurrent = (atom == txHTMLAtoms::script); - nsCOMPtr ssle = - do_QueryInterface(aElement); - if (ssle) { - // XXX Trick nsCSSLoader into blocking/notifying us? - // We would need to implement nsIParser and - // pass ourselves as first parameter to - // InitStyleLinkElement. We would then be notified - // of stylesheet loads/load failures. - ssle->InitStyleLinkElement(nsnull, PR_FALSE); - ssle->SetEnableUpdates(PR_FALSE); + if (mCreatingNewDocument) { + nsCOMPtr ssle = + do_QueryInterface(aElement); + if (ssle) { + // XXX Trick nsCSSLoader into blocking/notifying us? + // We would need to implement nsIParser and + // pass ourselves as first parameter to + // InitStyleLinkElement. We would then be notified + // of stylesheet loads/load failures. + ssle->InitStyleLinkElement(nsnull, PR_FALSE); + ssle->SetEnableUpdates(PR_FALSE); + } } } @@ -503,7 +496,8 @@ void txMozillaXMLOutput::endHTMLElement(nsIDOMElement* aElement, } } // Load scripts - else if (atom == txHTMLAtoms::script) { + else if (mCreatingNewDocument && + atom == txHTMLAtoms::script) { // Add this script element to the array of loading script elements. nsCOMPtr scriptElement = do_QueryInterface(mCurrentNode); @@ -515,7 +509,8 @@ void txMozillaXMLOutput::endHTMLElement(nsIDOMElement* aElement, mScriptElements->AppendElement(scriptElement); } // Set document title - else if (atom == txHTMLAtoms::title && !mHaveTitleElement) { + else if (mCreatingNewDocument && + atom == txHTMLAtoms::title && !mHaveTitleElement) { // The first title wins mHaveTitleElement = PR_TRUE; nsCOMPtr domDoc = do_QueryInterface(mDocument); @@ -528,7 +523,8 @@ void txMozillaXMLOutput::endHTMLElement(nsIDOMElement* aElement, domDoc->SetTitle(text); } } - else if (atom == txHTMLAtoms::base && !mHaveBaseElement) { + else if (mCreatingNewDocument && + atom == txHTMLAtoms::base && !mHaveBaseElement) { // The first base wins mHaveBaseElement = PR_TRUE; @@ -545,7 +541,8 @@ void txMozillaXMLOutput::endHTMLElement(nsIDOMElement* aElement, return; 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 nsAutoString httpEquiv; content->GetAttr(kNameSpaceID_None, txHTMLAtoms::httpEquiv, httpEquiv); @@ -563,7 +560,7 @@ void txMozillaXMLOutput::endHTMLElement(nsIDOMElement* aElement, } // Handle all sorts of stylesheets - if (!mDisableStylesheetLoad) { + if (mCreatingNewDocument) { nsCOMPtr ssle = do_QueryInterface(aElement); 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 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 loadGroup; + nsCOMPtr channel; + nsCOMPtr sourceDoc = do_QueryInterface(aSourceDocument); + sourceDoc->GetDocumentLoadGroup(getter_AddRefs(loadGroup)); + nsCOMPtr 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 docURL; + sourceDoc->GetDocumentURL(getter_AddRefs(docURL)); + serv->NewChannelFromURI(docURL, getter_AddRefs(channel)); + } + doc->Reset(channel, loadGroup); + nsCOMPtr 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 loader; + doc->GetScriptLoader(getter_AddRefs(loader)); + nsCOMPtr 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 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 documentType; + rv = implementation->CreateDocumentType(qName, + mOutputFormat.mPublicId, + mOutputFormat.mSystemId, + getter_AddRefs(documentType)); + NS_ASSERTION(NS_SUCCEEDED(rv), "Can't create doctype"); + nsCOMPtr 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 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 kungFuDeathGrip(this); + + mObserver = nsnull; + + // XXX Need a better way to determine transform success/failure + if (mDocument) { + nsCOMPtr loader; + nsCOMPtr 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); + } +} diff --git a/mozilla/extensions/transformiix/source/xslt/txMozillaXMLOutput.h b/mozilla/extensions/transformiix/source/xslt/txMozillaXMLOutput.h index 2d5884fd125..fcd23859329 100644 --- a/mozilla/extensions/transformiix/source/xslt/txMozillaXMLOutput.h +++ b/mozilla/extensions/transformiix/source/xslt/txMozillaXMLOutput.h @@ -44,17 +44,31 @@ #include "nsIDOMDocument.h" #include "nsIDOMHTMLTextAreaElement.h" #include "nsINameSpaceManager.h" +#include "nsIScriptLoader.h" +#include "nsIScriptLoaderObserver.h" #include "nsIStyleSheetLinkingElement.h" #include "nsString.h" #include "nsSupportsArray.h" +#include "nsWeakPtr.h" #include "txOutputFormat.h" -class txMozillaXMLOutput : public txMozillaXMLEventHandler +class txMozillaXMLOutput : public txIOutputXMLEventHandler, + public nsIScriptLoaderObserver { public: - txMozillaXMLOutput(); + txMozillaXMLOutput(const String& aRootName, + PRInt32 aRootNsID, + txOutputFormat* aFormat, + nsIDOMDocument* aSourceDocument, + nsIDOMDocument* aResultDocument, + nsITransformObserver* aObserver); + txMozillaXMLOutput(txOutputFormat* aFormat, + nsIDOMDocumentFragment* aFragment); virtual ~txMozillaXMLOutput(); + NS_DECL_ISUPPORTS + NS_DECL_NSISCRIPTLOADEROBSERVER + /** * Signals to receive the start of an attribute. * @@ -73,6 +87,16 @@ public: */ 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. * @@ -95,6 +119,18 @@ public: void endElement(const String& aName, 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. * @@ -118,31 +154,6 @@ public: void startElement(const String& aName, 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 * still loading. @@ -152,11 +163,11 @@ public: void removeScriptElement(nsIDOMHTMLScriptElement *aElement); /** - * Sets the Mozilla output document. + * Gets the Mozilla output document * * @param aDocument the Mozilla output document */ - void setOutputDocument(nsIDOMDocument* aDocument); + void getOutputDocument(nsIDOMDocument** aDocument); private: void closePrevious(PRInt8 aAction); @@ -164,11 +175,16 @@ private: void endHTMLElement(nsIDOMElement* aElement, PRBool aXHTML); void processHTTPEquiv(nsIAtom* aHeader, const nsAString& aValue); void wrapChildren(nsIDOMNode* aCurrentNode, nsIDOMElement* aWrapper); + nsresult createResultDocument(const String& aName, PRInt32 aNsID, + nsIDOMDocument* aSourceDocument, + nsIDOMDocument* aResultDocument); + void SignalTransformEnd(); nsCOMPtr mDocument; nsCOMPtr mCurrentNode; nsCOMPtr mParentNode; nsCOMPtr mRootContent; + nsWeakPtr mObserver; nsCOMPtr mNonAddedParent; nsCOMPtr mNonAddedNode; @@ -184,12 +200,14 @@ private: txOutputFormat mOutputFormat; - PRPackedBool mDisableStylesheetLoad; PRPackedBool mDontAddCurrent; PRPackedBool mHaveTitleElement; PRPackedBool mHaveBaseElement; + PRPackedBool mInTransform; + PRPackedBool mCreatingNewDocument; + enum txAction { eCloseElement = 1, eFlushText = 2 }; }; diff --git a/mozilla/extensions/transformiix/source/xslt/txMozillaXSLTProcessor.cpp b/mozilla/extensions/transformiix/source/xslt/txMozillaXSLTProcessor.cpp new file mode 100644 index 00000000000..1f7149c7acd --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/txMozillaXSLTProcessor.cpp @@ -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 (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 mSourceDocument; + nsCOMPtr mResultDocument; + nsCOMPtr mObserver; +}; + +class txToFragmentHandlerFactory : public txIOutputHandlerFactory +{ +public: + txToFragmentHandlerFactory(nsIDOMDocumentFragment* aFragment) + : mFragment(aFragment) + { + } + + virtual ~txToFragmentHandlerFactory() + { + } + + TX_DECL_TXIOUTPUTHANDLERFACTORY; + +private: + nsCOMPtr 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 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 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 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 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 styleDoc = do_QueryInterface(aStyleDOM); + nsresult rv; + if (styleDoc) { + rv = txXSLTProcessor::processStylesheet(&xslDocument, + &mVariables, &ps); + } + else { + nsCOMPtr 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 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 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 styleDoc = do_QueryInterface(aStyleDOM); + nsresult rv; + if (styleDoc) { + rv = txXSLTProcessor::processStylesheet(&xslDocument, + &mVariables, &ps); + } + else { + nsCOMPtr 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 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 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 styleDoc = do_QueryInterface(mStylesheet); + nsresult rv; + if (styleDoc) { + rv = txXSLTProcessor::processStylesheet(&xslDocument, + &mVariables, &ps); + } + else { + nsCOMPtr 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 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 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 styleDoc = do_QueryInterface(mStylesheet); + nsresult rv; + if (styleDoc) { + rv = txXSLTProcessor::processStylesheet(&xslDocument, + &mVariables, &ps); + } + else { + nsCOMPtr 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 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 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 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 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 namespaceManager = + do_GetService(kNameSpaceManagerCID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + PRInt32 nsId = kNameSpaceID_Unknown; + rv = namespaceManager->RegisterNameSpace(aNamespaceURI, nsId); + nsCOMPtr 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 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; +} diff --git a/mozilla/extensions/transformiix/source/xslt/txMozillaXSLTProcessor.h b/mozilla/extensions/transformiix/source/xslt/txMozillaXSLTProcessor.h new file mode 100644 index 00000000000..de391c59675 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/txMozillaXSLTProcessor.h @@ -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 (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 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 mStylesheet; + txExpandedNameMap mVariables; +}; + +#endif diff --git a/mozilla/extensions/transformiix/source/xslt/txStandaloneXSLTProcessor.cpp b/mozilla/extensions/transformiix/source/xslt/txStandaloneXSLTProcessor.cpp new file mode 100644 index 00000000000..dd89879cb56 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/txStandaloneXSLTProcessor.cpp @@ -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 (original author) + * Axel Hecht + * + * + * 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; +} diff --git a/mozilla/extensions/transformiix/source/xslt/txStandaloneXSLTProcessor.h b/mozilla/extensions/transformiix/source/xslt/txStandaloneXSLTProcessor.h new file mode 100644 index 00000000000..90c5e8beeed --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/txStandaloneXSLTProcessor.h @@ -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 (original author) + * Axel Hecht + * + * + * 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 +#include +#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 diff --git a/mozilla/extensions/transformiix/source/xslt/txTextOutput.cpp b/mozilla/extensions/transformiix/source/xslt/txTextOutput.cpp index 5bd3252575c..63da8d26235 100644 --- a/mozilla/extensions/transformiix/source/xslt/txTextOutput.cpp +++ b/mozilla/extensions/transformiix/source/xslt/txTextOutput.cpp @@ -39,7 +39,8 @@ #include "txTextOutput.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) { } - -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(); -} diff --git a/mozilla/extensions/transformiix/source/xslt/txTextOutput.h b/mozilla/extensions/transformiix/source/xslt/txTextOutput.h index ce3427237e6..46e5b122ca1 100644 --- a/mozilla/extensions/transformiix/source/xslt/txTextOutput.h +++ b/mozilla/extensions/transformiix/source/xslt/txTextOutput.h @@ -42,10 +42,10 @@ #include "txXMLEventHandler.h" #include "txOutputFormat.h" -class txTextOutput : public txStreamXMLEventHandler +class txTextOutput : public txIOutputXMLEventHandler { public: - txTextOutput(); + txTextOutput(ostream* aOut); ~txTextOutput(); /* @@ -95,6 +95,18 @@ public: void endElement(const String& aName, 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. * @@ -118,30 +130,8 @@ public: void startElement(const String& aName, 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: ostream* mOut; - txOutputFormat mOutputFormat; }; #endif diff --git a/mozilla/extensions/transformiix/source/xslt/txUnknownHandler.cpp b/mozilla/extensions/transformiix/source/xslt/txUnknownHandler.cpp index 1954e4e6c74..5c39e126923 100644 --- a/mozilla/extensions/transformiix/source/xslt/txUnknownHandler.cpp +++ b/mozilla/extensions/transformiix/source/xslt/txUnknownHandler.cpp @@ -38,12 +38,22 @@ #include "txUnknownHandler.h" #include +#include "ProcessorState.h" + +#ifndef TX_EXE +NS_IMPL_ISUPPORTS1(txUnknownHandler, txIOutputXMLEventHandler); +#endif PRUint32 txUnknownHandler::kReasonableTransactions = 8; -txUnknownHandler::txUnknownHandler() : mTotal(0), - mMax(kReasonableTransactions) +txUnknownHandler::txUnknownHandler(ProcessorState* aPs) + : mTotal(0), mMax(kReasonableTransactions), + mPs(aPs) { +#ifndef TX_EXE + NS_INIT_ISUPPORTS(); +#endif + mArray = new txOutputTransaction*[kReasonableTransactions]; } @@ -60,7 +70,9 @@ void txUnknownHandler::attribute(const String& aName, const PRInt32 aNsID, 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) @@ -69,7 +81,7 @@ void txUnknownHandler::characters(const String& aData) new txOneStringTransaction(txOutputTransaction::eCharacterTransaction, aData); if (!transaction) { - NS_ASSERTION(0, "Out of memory!") + NS_ASSERTION(0, "Out of memory!"); return; } addTransaction(transaction); @@ -81,7 +93,7 @@ void txUnknownHandler::charactersNoOutputEscaping(const String& aData) new txOneStringTransaction(txOutputTransaction::eCharacterNoOETransaction, aData); if (!transaction) { - NS_ASSERTION(0, "Out of memory!") + NS_ASSERTION(0, "Out of memory!"); return; } addTransaction(transaction); @@ -93,7 +105,7 @@ void txUnknownHandler::comment(const String& aData) new txOneStringTransaction(txOutputTransaction::eCommentTransaction, aData); if (!transaction) { - NS_ASSERTION(0, "Out of memory!") + NS_ASSERTION(0, "Out of memory!"); return; } addTransaction(transaction); @@ -101,19 +113,32 @@ void txUnknownHandler::comment(const String& aData) void txUnknownHandler::endDocument() { - txOutputTransaction* transaction = - new txOutputTransaction(txOutputTransaction::eEndDocumentTransaction); - if (!transaction) { - NS_ASSERTION(0, "Out of memory!") + // This is an unusual case, no output method has been set and we + // didn't create a document element. Switching to XML output mode + // anyway. + +#ifndef TX_EXE + // Make sure that we don't get deleted while this function is executed and + // we set a new outputhandler + nsCOMPtr kungFuDeathGrip(this); +#endif + nsresult rv = createHandlerAndFlush(eXMLOutput, String(), + kNameSpaceID_None); + if (NS_FAILED(rv)) return; - } - addTransaction(transaction); + + mPs->mResultHandler->endDocument(); + + // in module the outputhandler is refcounted +#ifdef TX_EXE + delete this; +#endif } void txUnknownHandler::endElement(const String& aName, 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, @@ -123,7 +148,7 @@ void txUnknownHandler::processingInstruction(const String& aTarget, new txTwoStringTransaction(txOutputTransaction::ePITransaction, aTarget, aData); if (!transaction) { - NS_ASSERTION(0, "Out of memory!") + NS_ASSERTION(0, "Out of memory!"); return; } addTransaction(transaction); @@ -134,7 +159,7 @@ void txUnknownHandler::startDocument() txOutputTransaction* transaction = new txOutputTransaction(txOutputTransaction::eStartDocumentTransaction); if (!transaction) { - NS_ASSERTION(0, "Out of memory!") + NS_ASSERTION(0, "Out of memory!"); return; } addTransaction(transaction); @@ -143,74 +168,108 @@ void txUnknownHandler::startDocument() void txUnknownHandler::startElement(const String& aName, 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 kungFuDeathGrip(this); +#endif -void txUnknownHandler::setOutputFormat(txOutputFormat* aOutputFormat) -{ -} - -void txUnknownHandler::getOutputStream(ostream** aOutputStream) -{ - if (aOutputStream) { - *aOutputStream = mOut; + nsresult rv = NS_OK; + txOutputFormat* format = mPs->getOutputFormat(); + if (format->mMethod != eMethodNotSet) { + rv = createHandlerAndFlush(format->mMethod, aName, aNsID); } + 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; for (counter = 0; counter < mTotal; ++counter) { switch (mArray[counter]->mType) { case txOutputTransaction::eCharacterTransaction: { txOneStringTransaction* transaction = (txOneStringTransaction*)mArray[counter]; - aHandler->characters(transaction->mString); + handler->characters(transaction->mString); delete transaction; break; } case txOutputTransaction::eCharacterNoOETransaction: { txOneStringTransaction* transaction = (txOneStringTransaction*)mArray[counter]; - aHandler->charactersNoOutputEscaping(transaction->mString); + if (hasDOE) { + handler->charactersNoOutputEscaping(transaction->mString); + } + else { + handler->characters(transaction->mString); + } delete transaction; break; } case txOutputTransaction::eCommentTransaction: { txOneStringTransaction* transaction = (txOneStringTransaction*)mArray[counter]; - aHandler->comment(transaction->mString); + handler->comment(transaction->mString); delete transaction; break; } - case txOutputTransaction::eEndDocumentTransaction: - { - aHandler->endDocument(); - delete mArray[counter]; - break; - } case txOutputTransaction::ePITransaction: { txTwoStringTransaction* transaction = (txTwoStringTransaction*)mArray[counter]; - aHandler->processingInstruction(transaction->mStringOne, + handler->processingInstruction(transaction->mStringOne, transaction->mStringTwo); delete transaction; break; } case txOutputTransaction::eStartDocumentTransaction: { - aHandler->startDocument(); + handler->startDocument(); delete mArray[counter]; break; } } } mTotal = 0; + + return NS_OK; } void txUnknownHandler::addTransaction(txOutputTransaction* aTransaction) @@ -219,7 +278,7 @@ void txUnknownHandler::addTransaction(txOutputTransaction* aTransaction) PRUint32 newMax = mMax * 2; txOutputTransaction** newArray = new txOutputTransaction*[newMax]; if (!newArray) { - NS_ASSERTION(0, "Out of memory!") + NS_ASSERTION(0, "Out of memory!"); return; } mMax = newMax; diff --git a/mozilla/extensions/transformiix/source/xslt/txUnknownHandler.h b/mozilla/extensions/transformiix/source/xslt/txUnknownHandler.h index d361b59516c..173f88108d2 100644 --- a/mozilla/extensions/transformiix/source/xslt/txUnknownHandler.h +++ b/mozilla/extensions/transformiix/source/xslt/txUnknownHandler.h @@ -41,6 +41,9 @@ #include "txXMLEventHandler.h" #include "TxString.h" +#include "txOutputFormat.h" + +class ProcessorState; class txOutputTransaction { @@ -49,7 +52,6 @@ public: eCharacterTransaction, eCharacterNoOETransaction, eCommentTransaction, - eEndDocumentTransaction, ePITransaction, eStartDocumentTransaction }; @@ -90,12 +92,16 @@ public: String mStringTwo; }; -class txUnknownHandler : public txStreamXMLEventHandler +class txUnknownHandler : public txIOutputXMLEventHandler { public: - txUnknownHandler(); + txUnknownHandler(ProcessorState* aPs); virtual ~txUnknownHandler(); +#ifndef TX_EXE + NS_DECL_ISUPPORTS +#endif + /* * Signals to receive the start of an attribute. * @@ -143,6 +149,18 @@ public: void endElement(const String& aName, 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. * @@ -165,34 +183,29 @@ public: */ void startElement(const String& aName, 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); - - /* - * Sets the output stream. - * - * @param aOutputStream the output stream - */ - void setOutputStream(ostream* aOutputStream); - - void flush(txStreamXMLEventHandler* aHandler); + void getOutputDocument(nsIDOMDocument** aDocument); +#endif private: + nsresult createHandlerAndFlush(txOutputMethod aMethod, + const String& aName, + const PRInt32 aNsID); void addTransaction(txOutputTransaction* aTransaction); 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; static PRUint32 kReasonableTransactions; diff --git a/mozilla/extensions/transformiix/source/xslt/txXMLEventHandler.h b/mozilla/extensions/transformiix/source/xslt/txXMLEventHandler.h index 6b3e878d764..48e18f090cd 100644 --- a/mozilla/extensions/transformiix/source/xslt/txXMLEventHandler.h +++ b/mozilla/extensions/transformiix/source/xslt/txXMLEventHandler.h @@ -25,14 +25,20 @@ #define TRANSFRMX_XML_EVENT_HANDLER_H #include "baseutils.h" +#include "txError.h" class String; class txOutputFormat; #ifdef TX_EXE #include #else +#include "nsISupports.h" +#define kTXNameSpaceURI "http://www.mozilla.org/TransforMiix" +#define kTXWrapper "transformiix:result" + class nsIContent; class nsIDOMDocument; class nsIDOMHTMLScriptElement; +class nsITransformObserver; #endif /** @@ -109,79 +115,84 @@ public: 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 -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: - /** - * 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. * * @param aData the characters to receive */ 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 - * 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. + * Gets the Mozilla output document * * @param aDocument the Mozilla output document */ - virtual void setOutputDocument(nsIDOMDocument* aDocument) = 0; -}; + virtual void getOutputDocument(nsIDOMDocument** aDocument) = 0; #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 diff --git a/mozilla/extensions/transformiix/source/xslt/txXMLOutput.cpp b/mozilla/extensions/transformiix/source/xslt/txXMLOutput.cpp index 9d4dd494a21..852632a288d 100644 --- a/mozilla/extensions/transformiix/source/xslt/txXMLOutput.cpp +++ b/mozilla/extensions/transformiix/source/xslt/txXMLOutput.cpp @@ -47,13 +47,17 @@ txAttribute::txAttribute(PRInt32 aNsID, txAtom* aLocalName, const String& aValue { } -txXMLOutput::txXMLOutput() : mUseEmptyElementShorthand(MB_TRUE), - mHaveDocumentElement(MB_FALSE), - mStartTagOpen(MB_FALSE), - mAfterEndTag(MB_FALSE), - mInCDATASection(MB_FALSE), - mIndentLevel(0) +txXMLOutput::txXMLOutput(txOutputFormat* aFormat, ostream* aOut) + : mOut(aOut), + mUseEmptyElementShorthand(MB_TRUE), + mHaveDocumentElement(MB_FALSE), + mStartTagOpen(MB_FALSE), + mAfterEndTag(MB_FALSE), + mInCDATASection(MB_FALSE), + mIndentLevel(0) { + mOutputFormat.merge(*aFormat); + mOutputFormat.setFromDefaults(); } 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) { mAfterEndTag = aUseEmptyElementShorthand; diff --git a/mozilla/extensions/transformiix/source/xslt/txXMLOutput.h b/mozilla/extensions/transformiix/source/xslt/txXMLOutput.h index 4aa9c9d1cad..ac6f2acafb7 100644 --- a/mozilla/extensions/transformiix/source/xslt/txXMLOutput.h +++ b/mozilla/extensions/transformiix/source/xslt/txXMLOutput.h @@ -91,10 +91,10 @@ public: MBool mShorthand; }; -class txXMLOutput : public txStreamXMLEventHandler +class txXMLOutput : public txIOutputXMLEventHandler { public: - txXMLOutput(); + txXMLOutput(txOutputFormat* aFormat, ostream* aOut); virtual ~txXMLOutput(); static const int DEFAULT_INDENT; @@ -146,6 +146,18 @@ public: virtual void endElement(const String& aName, 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. * @@ -169,27 +181,6 @@ public: virtual void startElement(const String& aName, 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: virtual void closeStartTag(MBool aUseEmptyElementShorthand); void printUTF8Char(DOM_CHAR& ch);