diff --git a/mozilla/content/macbuild/content.xml b/mozilla/content/macbuild/content.xml index 4e857356ff0..e69e80d5b8c 100644 --- a/mozilla/content/macbuild/content.xml +++ b/mozilla/content/macbuild/content.xml @@ -1808,20 +1808,6 @@ Text Debug - - Name - nsTransformMediator.cpp - MacOS - Text - Debug - - - Name - nsXSLContentSink.cpp - MacOS - Text - Debug - Name nsElementMap.cpp @@ -3071,16 +3057,6 @@ nsStyleContext.cpp MacOS - - Name - nsTransformMediator.cpp - MacOS - - - Name - nsXSLContentSink.cpp - MacOS - Name nsElementMap.cpp @@ -5168,20 +5144,6 @@ Text Debug - - Name - nsTransformMediator.cpp - MacOS - Text - Debug - - - Name - nsXSLContentSink.cpp - MacOS - Text - Debug - Name nsElementMap.cpp @@ -6431,16 +6393,6 @@ nsStyleContext.cpp MacOS - - Name - nsTransformMediator.cpp - MacOS - - - Name - nsXSLContentSink.cpp - MacOS - Name nsElementMap.cpp @@ -7871,20 +7823,6 @@ MacOS - xsl - - content.o - Name - nsTransformMediator.cpp - MacOS - - - content.o - Name - nsXSLContentSink.cpp - MacOS - - xul/content content.o diff --git a/mozilla/content/macbuild/contentIDL.xml b/mozilla/content/macbuild/contentIDL.xml index 6848adc95f1..ae82164a483 100644 --- a/mozilla/content/macbuild/contentIDL.xml +++ b/mozilla/content/macbuild/contentIDL.xml @@ -95,16 +95,6 @@ FrameworkPathfalse HostFlagsAll - - SearchPath - Path::xsl:document:src: - PathFormatMacOS - PathRootProject - - Recursivetrue - FrameworkPathfalse - HostFlagsAll - SearchPath Path::xul:document:public: @@ -1154,16 +1144,6 @@ FrameworkPathfalse HostFlagsAll - - SearchPath - Path::xsl:document:src: - PathFormatMacOS - PathRootProject - - Recursivetrue - FrameworkPathfalse - HostFlagsAll - SearchPath Path::xul:document:public: diff --git a/mozilla/content/xml/document/src/nsXMLContentSink.cpp b/mozilla/content/xml/document/src/nsXMLContentSink.cpp index 35155f86450..e419c6a6c3f 100644 --- a/mozilla/content/xml/document/src/nsXMLContentSink.cpp +++ b/mozilla/content/xml/document/src/nsXMLContentSink.cpp @@ -85,7 +85,6 @@ #include "prtime.h" #include "prlog.h" #include "prmem.h" -#include "nsXSLContentSink.h" #include "nsParserCIID.h" #include "nsParserUtils.h" #include "nsIScrollable.h" @@ -438,13 +437,12 @@ nsXMLContentSink::DidBuildModel(PRInt32 aQualityLevel) // Check if we want to prettyprint MaybePrettyPrint(); - if (mXSLTransformMediator) { + if (mXSLTProcessor) { nsCOMPtr currentDOMDoc(do_QueryInterface(mDocument)); - mXSLTransformMediator->SetSourceContentModel(currentDOMDoc); - mXSLTransformMediator->SetTransformObserver(this); - // Since the mediator now holds a reference to us we drop our reference + mXSLTProcessor->SetSourceContentModel(currentDOMDoc); + // Since the processor now holds a reference to us we drop our reference // to it to avoid owning cycles - mXSLTransformMediator = nsnull; + mXSLTProcessor = nsnull; } else { // Kick off layout for non-XSLT transformed documents. @@ -785,59 +783,23 @@ nsXMLContentSink::AddContentAsLeaf(nsIContent *aContent) nsresult nsXMLContentSink::LoadXSLStyleSheet(nsIURI* aUrl) { - nsresult rv = NS_OK; - - // Create a transform mediator - rv = NS_NewTransformMediator(getter_AddRefs(mXSLTransformMediator), - NS_LITERAL_CSTRING(kXSLType)); - if (NS_FAILED(rv)) { + mXSLTProcessor = + do_CreateInstance("@mozilla.org/document-transformer;1?type=text/xslt"); + if (!mXSLTProcessor) { // No XSLT processor available, continue normal document loading return NS_OK; } - // Enable the transform mediator. It will start the transform - // as soon as it has enough state to do so. The state needed is - // the source content model, the style content model, the current - // document, and an observer. The XML and XSL content sinks provide - // this state by calling the various setters on nsITransformMediator. - mXSLTransformMediator->SetEnabled(PR_TRUE); + mXSLTProcessor->SetTransformObserver(this); - // Create and set up the channel nsCOMPtr loadGroup; - rv = mDocument->GetDocumentLoadGroup(getter_AddRefs(loadGroup)); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr channel; - rv = NS_NewChannel(getter_AddRefs(channel), aUrl); - if (NS_FAILED(rv)) return rv; - - channel->SetLoadGroup(loadGroup); - - nsCOMPtr httpChannel(do_QueryInterface(channel)); - if (httpChannel) { - httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Accept"), - NS_LITERAL_CSTRING("text/xml,application/xml,application/xhtml+xml,*/*;q=0.1"), - PR_FALSE); - - httpChannel->SetReferrer(mDocumentURL); + nsresult rv = mDocument->GetDocumentLoadGroup(getter_AddRefs(loadGroup)); + if (NS_FAILED(rv)) { + mXSLTProcessor = nsnull; + return rv; } - - // Create the XSL stylesheet document - nsCOMPtr styleDoc = do_CreateInstance(kXMLDocumentCID, &rv); - NS_ENSURE_SUCCESS(rv, rv); - - // Create the XSL content sink - nsCOMPtr sink; - rv = NS_NewXSLContentSink(getter_AddRefs(sink), mXSLTransformMediator, styleDoc, aUrl, mWebShell); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr sl; - rv = styleDoc->StartDocumentLoad(kLoadAsData, channel, loadGroup, nsnull, - getter_AddRefs(sl), PR_TRUE, sink); - NS_ENSURE_SUCCESS(rv, rv); - - return channel->AsyncOpen(sl, nsnull); + return mXSLTProcessor->LoadStyleSheet(aUrl, loadGroup, mDocumentURL); } NS_IMETHODIMP @@ -871,7 +833,7 @@ nsXMLContentSink::ProcessStyleLink(nsIContent* aElement, rv = NS_NewURI(getter_AddRefs(url), aHref, nsnull, mDocumentBaseURL); NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr secMan = + nsCOMPtr secMan = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, NS_OK); @@ -1817,7 +1779,7 @@ nsXMLContentSink::HandleStartElement(const PRUnichar *aName, // For XSLT, we need to wait till after the transform // to set the root content object. - if (!mXSLTransformMediator) { + if (!mXSLTProcessor) { mDocument->SetRootContent(mDocElement); } } @@ -2101,10 +2063,10 @@ nsXMLContentSink::ReportError(const PRUnichar* aErrorText, } NS_IF_RELEASE(mDocElement); - if (mXSLTransformMediator) { - // Get rid of the transform mediator. - mXSLTransformMediator->SetEnabled(PR_FALSE); - mXSLTransformMediator = nsnull; + if (mXSLTProcessor) { + // Get rid of the XSLT processor. + mXSLTProcessor->CancelLoads(); + mXSLTProcessor = nsnull; } NS_NAMED_LITERAL_STRING(name, "xmlns"); diff --git a/mozilla/content/xml/document/src/nsXMLContentSink.h b/mozilla/content/xml/document/src/nsXMLContentSink.h index 9c921097d08..e4c640d5f55 100644 --- a/mozilla/content/xml/document/src/nsXMLContentSink.h +++ b/mozilla/content/xml/document/src/nsXMLContentSink.h @@ -43,13 +43,11 @@ #include "nsIViewManager.h" #include "nsIScrollableView.h" #include "nsWeakReference.h" -#include "nsITransformMediator.h" #include "nsIUnicharInputStream.h" #include "nsIStreamLoader.h" #include "nsISupportsArray.h" #include "nsINodeInfo.h" #include "nsIDOMHTMLTextAreaElement.h" -class nsICSSStyleSheet; #include "nsICSSLoaderObserver.h" #include "nsIHTMLContent.h" #include "nsIDOMHTMLScriptElement.h" @@ -59,6 +57,7 @@ class nsICSSStyleSheet; #include "nsIExpatSink.h" #include "nsIDocumentTransformer.h" +class nsICSSStyleSheet; class nsIDocument; class nsIURI; class nsIWebShell; @@ -204,7 +203,7 @@ protected: nsCOMPtr mContentStack; nsCOMPtr mNodeInfoManager; - nsCOMPtr mXSLTransformMediator; + nsCOMPtr mXSLTProcessor; }; #endif // nsXMLContentSink_h__ diff --git a/mozilla/content/xsl/Makefile.in b/mozilla/content/xsl/Makefile.in index 3c0e05b136f..6a59c6f5621 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 = public document +DIRS = public include $(topsrcdir)/config/config.mk diff --git a/mozilla/content/xsl/document/Makefile.in b/mozilla/content/xsl/document/Makefile.in deleted file mode 100755 index e98c66370c1..00000000000 --- a/mozilla/content/xsl/document/Makefile.in +++ /dev/null @@ -1,28 +0,0 @@ -# -# The contents of this file are subject to the Netscape Public License -# Version 1.0 (the "NPL"); you may not use this file except in -# compliance with the NPL. You may obtain a copy of the NPL at -# http://www.mozilla.org/NPL/ -# -# Software distributed under the NPL is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL -# for the specific language governing rights and limitations under the -# NPL. -# -# The Initial Developer of this code under the NPL is Netscape -# Communications Corporation. Portions created by Netscape are -# Copyright (C) 1998 Netscape Communications Corporation. All Rights -# Reserved. - -DEPTH = ../../.. -topsrcdir = @top_srcdir@ -srcdir = @srcdir@ -VPATH = @srcdir@ - -include $(DEPTH)/config/autoconf.mk - -DIRS = src - -include $(topsrcdir)/config/config.mk - -include $(topsrcdir)/config/rules.mk diff --git a/mozilla/content/xsl/document/src/Makefile.in b/mozilla/content/xsl/document/src/Makefile.in deleted file mode 100755 index 1274befcd1f..00000000000 --- a/mozilla/content/xsl/document/src/Makefile.in +++ /dev/null @@ -1,54 +0,0 @@ -#!gmake -# -# The contents of this file are subject to the Netscape Public License -# Version 1.0 (the "NPL"); you may not use this file except in -# compliance with the NPL. You may obtain a copy of the NPL at -# http://www.mozilla.org/NPL/ -# -# Software distributed under the NPL is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL -# for the specific language governing rights and limitations under the -# NPL. -# -# The Initial Developer of this code under the NPL is Netscape -# Communications Corporation. Portions created by Netscape are -# Copyright (C) 1998 Netscape Communications Corporation. All Rights -# Reserved. - -DEPTH=../../../.. -topsrcdir = @top_srcdir@ -srcdir = @srcdir@ -VPATH = @srcdir@ - -include $(DEPTH)/config/autoconf.mk - -MODULE = content -LIBRARY_NAME = gkconxsldoc_s -REQUIRES = xpcom \ - string \ - htmlparser \ - view \ - widget \ - dom \ - necko \ - gfx \ - layout \ - content \ - $(NULL) - -include $(topsrcdir)/config/config.mk - -CPPSRCS = \ - nsXSLContentSink.cpp \ - nsTransformMediator.cpp \ - $(NULL) - -LOCAL_INCLUDES = \ - -I$(srcdir)/../../../xml/document/src \ - $(NULL) - -# we don't want the shared lib, but we want to force the creation of a static lib. -FORCE_STATIC_LIB = 1 - -include $(topsrcdir)/config/rules.mk - diff --git a/mozilla/content/xsl/document/src/nsTransformMediator.cpp b/mozilla/content/xsl/document/src/nsTransformMediator.cpp deleted file mode 100644 index c7f6e5718b6..00000000000 --- a/mozilla/content/xsl/document/src/nsTransformMediator.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: NPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Netscape 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/NPL/ - * - * 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 Communicator client code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * - * 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 NPL, 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 NPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "nsTransformMediator.h" -#include "nsIComponentManager.h" -#include "nsString.h" - -nsresult -NS_NewTransformMediator(nsITransformMediator** aInstancePtrResult, - const nsACString& aMimeType) -{ - NS_ENSURE_ARG_POINTER(aInstancePtrResult); - - nsTransformMediator* it; - NS_NEWXPCOM(it, nsTransformMediator); - if (!it) { - return NS_ERROR_OUT_OF_MEMORY; - } - nsresult rv = it->Init(aMimeType); - if (NS_FAILED(rv)) { - delete it; - return rv; - } - return CallQueryInterface(it, aInstancePtrResult); -} - -nsTransformMediator::nsTransformMediator() : mEnabled(PR_FALSE), - mStyleInvalid(PR_FALSE) -{ -} - -nsTransformMediator::~nsTransformMediator() -{ -} - -static -nsresult ConstructContractID(nsACString& aContractID, - const nsACString& aMimeType) -{ - aContractID.Assign(NS_LITERAL_CSTRING("@mozilla.org/document-transformer;1?type=")); - aContractID.Append(aMimeType); - return NS_OK; -} - -nsresult -nsTransformMediator::Init(const nsACString& aMimeType) -{ - // Construct prog ID for the document tranformer component - nsCAutoString contractID; - nsresult rv = ConstructContractID(contractID, aMimeType); - if (NS_SUCCEEDED(rv)) { - // Try to find a component that implements the nsIDocumentTransformer interface - mTransformer = do_CreateInstance(contractID.get(), &rv); - } - return rv; -} - -// nsISupports -NS_IMPL_ISUPPORTS1(nsTransformMediator, nsITransformMediator) - -void -nsTransformMediator::TryToTransform() -{ - if (mSourceDOM && mStyleDOM && mObserver) - { - if (mEnabled && mTransformer) { - mTransformer->TransformDocument(mSourceDOM, - mStyleDOM, - mObserver, - getter_AddRefs(mResultDoc)); - } - else if (mStyleInvalid) { - // Avoid recursion. - mStyleInvalid = PR_FALSE; - - // Notify the observer with the stylesheet which contains - // the error message. - nsCOMPtr errorDoc; - mStyleDOM->GetOwnerDocument(getter_AddRefs(errorDoc)); - mObserver->OnTransformDone(NS_ERROR_FAILURE, errorDoc); - } - } -} - -// nsITransformMediator -NS_IMETHODIMP -nsTransformMediator::SetEnabled(PRBool aValue) -{ - mEnabled = aValue; - TryToTransform(); - return NS_OK; -} - -NS_IMETHODIMP -nsTransformMediator::SetSourceContentModel(nsIDOMNode* aSource) -{ - mSourceDOM = aSource; - TryToTransform(); - return NS_OK; -} - -NS_IMETHODIMP -nsTransformMediator::SetStyleSheetContentModel(nsIDOMNode* aStyle) -{ - mStyleDOM = aStyle; - TryToTransform(); - return NS_OK; -} - -NS_IMETHODIMP -nsTransformMediator::GetResultDocument(nsIDOMDocument** aDoc) -{ - *aDoc = mResultDoc; - NS_IF_ADDREF(*aDoc); - return NS_OK; -} - -NS_IMETHODIMP -nsTransformMediator::SetTransformObserver(nsITransformObserver* aObserver) -{ - mObserver = aObserver; - TryToTransform(); - return NS_OK; -} - -NS_IMETHODIMP -nsTransformMediator::SetStyleInvalid(PRBool aInvalid) -{ - mStyleInvalid = aInvalid; - return NS_OK; -} diff --git a/mozilla/content/xsl/document/src/nsTransformMediator.h b/mozilla/content/xsl/document/src/nsTransformMediator.h deleted file mode 100644 index 581e68001d2..00000000000 --- a/mozilla/content/xsl/document/src/nsTransformMediator.h +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: NPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Netscape 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/NPL/ - * - * 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 Communicator client code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * - * 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 NPL, 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 NPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef nsTransformMediator_h__ -#define nsTransformMediator_h__ - -#include "nsCOMPtr.h" -#include "nsITransformMediator.h" -#include "nsIDocumentTransformer.h" -#include "nsIDOMNode.h" -#include "nsIDOMDocument.h" - -class nsTransformMediator : public nsITransformMediator { -public: - nsTransformMediator(); - virtual ~nsTransformMediator(); - - nsresult Init(const nsACString& aMimeType); - - // nsISupports - NS_DECL_ISUPPORTS - - // nsITransformMediator - NS_IMETHOD SetEnabled(PRBool aValue); - NS_IMETHOD SetSourceContentModel(nsIDOMNode* aSource); - NS_IMETHOD SetStyleSheetContentModel(nsIDOMNode* aStyle); - NS_IMETHOD GetResultDocument(nsIDOMDocument** aDoc); - NS_IMETHOD SetTransformObserver(nsITransformObserver* aObserver); - NS_IMETHOD SetStyleInvalid(PRBool aInvalid); - -protected: - void TryToTransform(); - - PRBool mEnabled; - PRBool mStyleInvalid; - nsCOMPtr mTransformer; - nsCOMPtr mSourceDOM; - nsCOMPtr mStyleDOM; - nsCOMPtr mResultDoc; - nsCOMPtr mObserver; -}; - -#endif // nsTransformMediator_h__ diff --git a/mozilla/content/xsl/document/src/nsXSLContentSink.cpp b/mozilla/content/xsl/document/src/nsXSLContentSink.cpp deleted file mode 100644 index deb0200989b..00000000000 --- a/mozilla/content/xsl/document/src/nsXSLContentSink.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: NPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Netscape 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/NPL/ - * - * 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 Communicator client code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * - * 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 NPL, 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 NPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "nsXSLContentSink.h" -#include "nsHTMLAtoms.h" -#include "nsIDocument.h" -#include "nsIDOMDocument.h" -#include "nsIDOMElement.h" -#include "nsILoadGroup.h" -#include "nsIParser.h" -#include "nsIStyleSheetLinkingElement.h" -#include "nsITransformMediator.h" -#include "nsIURL.h" -#include "nsString.h" -#include "nsEscape.h" - -nsresult -NS_NewXSLContentSink(nsIXMLContentSink** aResult, - nsITransformMediator* aTM, - nsIDocument* aDoc, - nsIURI* aURL, - nsIWebShell* aWebShell) -{ - NS_ENSURE_ARG(aResult); - - nsXSLContentSink* it; - NS_NEWXPCOM(it, nsXSLContentSink); - NS_ENSURE_TRUE(it, NS_ERROR_OUT_OF_MEMORY); - - nsCOMPtr sink = it; - nsresult rv = it->Init(aTM, aDoc, aURL, aWebShell); - NS_ENSURE_SUCCESS(rv, rv); - - return CallQueryInterface(it, aResult); -} - -nsXSLContentSink::nsXSLContentSink() -{ - // Empty -} - -nsXSLContentSink::~nsXSLContentSink() -{ - // Empty -} - -nsresult -nsXSLContentSink::Init(nsITransformMediator* aTM, - nsIDocument* aDoc, - nsIURI* aURL, - nsIWebShell* aContainer) -{ - nsresult rv = nsXMLContentSink::Init(aDoc, aURL, aContainer, nsnull); - NS_ENSURE_SUCCESS(rv, rv); - - mXSLTransformMediator = aTM; - - return rv; -} - -// nsIContentSink -NS_IMETHODIMP -nsXSLContentSink::WillBuildModel(void) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsXSLContentSink::DidBuildModel(PRInt32 aQualityLevel) -{ - mDocument->SetRootContent(mDocElement); - mDocument->EndLoad(); - - nsCOMPtr styleNode; - nsCOMPtr url = do_QueryInterface(mDocumentURL); - if (url) { - nsCAutoString ref; - url->GetRef(ref); - if (!ref.IsEmpty()) { - NS_UnescapeURL(ref); // XXX this may result in non-ASCII octets - nsCOMPtr styleDoc = do_QueryInterface(mDocument); - NS_ENSURE_TRUE(styleDoc, NS_ERROR_NO_INTERFACE); - nsCOMPtr elem; - styleDoc->GetElementById(NS_ConvertUTF8toUCS2(ref), - getter_AddRefs(elem)); - styleNode = elem; - } - else { - styleNode = do_QueryInterface(mDocument); - } - } - else { - styleNode = do_QueryInterface(mDocument); - } - - if (mXSLTransformMediator) { - // Pass the style content model to the tranform mediator. - mXSLTransformMediator->SetStyleSheetContentModel(styleNode); - mXSLTransformMediator = nsnull; - } - - // Drop our reference to the parser to get rid of a circular - // reference. - NS_IF_RELEASE(mParser); - - return NS_OK; -} - -// To stop infinite recursive processing of -NS_IMETHODIMP -nsXSLContentSink::ProcessStyleLink(nsIContent* aElement, - const nsString& aHref, - PRBool aAlternate, - const nsString& aTitle, - const nsString& aType, - const nsString& aMedia) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsXSLContentSink::ReportError(const PRUnichar* aErrorText, - const PRUnichar* aSourceText) -{ - // nsXMLContentSink::ReportError sets mXSLTransformMediator to nsnull - nsCOMPtr mediator = mXSLTransformMediator; - - nsCOMPtr channel; - nsCOMPtr loadGroup; - mParser->GetChannel(getter_AddRefs(channel)); - mDocument->GetDocumentLoadGroup(getter_AddRefs(loadGroup)); - mDocument->Reset(channel, loadGroup); - - nsXMLContentSink::ReportError(aErrorText, aSourceText); - - if (mediator) { - nsCOMPtr styleNode = do_QueryInterface(mDocElement); - mediator->SetStyleInvalid(PR_TRUE); - mediator->SetStyleSheetContentModel(styleNode); - } - return NS_OK; -} - -nsresult -nsXSLContentSink::CreateElement(const PRUnichar** aAtts, PRUint32 aAttsCount, - nsINodeInfo* aNodeInfo, PRUint32 aLineNumber, - nsIContent** aResult, PRBool* aAppendContent) -{ - *aAppendContent = PR_TRUE; - return NS_NewXMLElement(aResult, aNodeInfo); -} - -nsresult -nsXSLContentSink::CloseElement(nsIContent* aContent, PRBool* aAppendContent) -{ - *aAppendContent = PR_FALSE; - return NS_OK; -} diff --git a/mozilla/content/xsl/document/src/nsXSLContentSink.h b/mozilla/content/xsl/document/src/nsXSLContentSink.h deleted file mode 100644 index e19cb276385..00000000000 --- a/mozilla/content/xsl/document/src/nsXSLContentSink.h +++ /dev/null @@ -1,89 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: NPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Netscape 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/NPL/ - * - * 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 Communicator client code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * - * 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 NPL, 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 NPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef nsXSLContentSink_h__ -#define nsXSLContentSink_h__ - -#include "nsXMLContentSink.h" - -// The XSL content sink accepts a parsed XML document -// from the parser and creates a XSL rule data model -// and an XSL stylesheet content model. - -class nsXSLContentSink : public nsXMLContentSink { -public: - nsXSLContentSink(); - ~nsXSLContentSink(); - - nsresult Init(nsITransformMediator* aTM, - nsIDocument* aDoc, - nsIURI* aURL, - nsIWebShell* aContainer); - - // nsIContentSink - NS_IMETHOD WillBuildModel(void); - NS_IMETHOD DidBuildModel(PRInt32 aQualityLevel); - - // nsIExpatSink - NS_IMETHOD ReportError(const PRUnichar *aErrorText, - const PRUnichar *aSourceText); - -protected: - // override nsXMLContentSink hooks - nsresult CreateElement(const PRUnichar** aAtts, PRUint32 aAttsCount, - nsINodeInfo* aNodeInfo, PRUint32 aLineNumber, - nsIContent** aResult, PRBool* aAppendContent); - - nsresult CloseElement(nsIContent* aContent, PRBool* aAppendContent); - - NS_IMETHOD ProcessStyleLink(nsIContent* aElement, - const nsString& aHref, - PRBool aAlternate, - const nsString& aTitle, - const nsString& aType, - const nsString& aMedia); -}; - - -nsresult -NS_NewXSLContentSink(nsIXMLContentSink** aResult, - nsITransformMediator* aTM, - nsIDocument* aDoc, - nsIURI* aURL, - nsIWebShell* aWebShell); -#endif // nsXSLContentSink_h__ diff --git a/mozilla/content/xsl/public/MANIFEST b/mozilla/content/xsl/public/MANIFEST index 1664c6b2a45..84ac6c661e5 100644 --- a/mozilla/content/xsl/public/MANIFEST +++ b/mozilla/content/xsl/public/MANIFEST @@ -2,5 +2,4 @@ # 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/Makefile.in b/mozilla/content/xsl/public/Makefile.in index 70d8fdfc402..3dbb06df01b 100644 --- a/mozilla/content/xsl/public/Makefile.in +++ b/mozilla/content/xsl/public/Makefile.in @@ -47,7 +47,6 @@ XPIDL_MODULE = content_xslt EXPORTS = \ nsIDocumentTransformer.h \ - nsITransformMediator.h \ $(NULL) XPIDLSRCS = \ diff --git a/mozilla/content/xsl/public/nsIDocumentTransformer.h b/mozilla/content/xsl/public/nsIDocumentTransformer.h index 28c83f14466..20d6b743497 100644 --- a/mozilla/content/xsl/public/nsIDocumentTransformer.h +++ b/mozilla/content/xsl/public/nsIDocumentTransformer.h @@ -42,6 +42,8 @@ class nsIDOMDocument; class nsIDOMNode; +class nsILoadGroup; +class nsIURI; #define NS_ITRANSFORMOBSERVER_IID \ {0xcce88481, 0x6eb3, 0x11d6, \ @@ -55,7 +57,8 @@ public: NS_IMETHOD OnDocumentCreated(nsIDOMDocument *aResultDocument) = 0; - NS_IMETHOD OnTransformDone(nsresult aResult, nsIDOMDocument *aResultDocument) = 0; + NS_IMETHOD OnTransformDone(nsresult aResult, + nsIDOMDocument *aResultDocument) = 0; }; @@ -69,10 +72,11 @@ public: NS_DEFINE_STATIC_IID_ACCESSOR(NS_IDOCUMENTTRANSFORMER_IID) - NS_IMETHOD TransformDocument(nsIDOMNode *aSourceDOM, - nsIDOMNode *aStyleDOM, - nsITransformObserver *aObserver, - nsIDOMDocument **_retval) = 0; + NS_IMETHOD SetTransformObserver(nsITransformObserver* aObserver) = 0; + NS_IMETHOD LoadStyleSheet(nsIURI* aUri, nsILoadGroup* aLoadGroup, + nsIURI* aReferrerUri) = 0; + NS_IMETHOD SetSourceContentModel(nsIDOMNode* aSource) = 0; + NS_IMETHOD CancelLoads() = 0; }; #endif //nsIDocumentTransformer_h__ diff --git a/mozilla/extensions/transformiix/build/Makefile.in b/mozilla/extensions/transformiix/build/Makefile.in index 3c99c886559..4bd5a288c42 100644 --- a/mozilla/extensions/transformiix/build/Makefile.in +++ b/mozilla/extensions/transformiix/build/Makefile.in @@ -47,6 +47,7 @@ REQUIRES = xpcom \ webshell \ docshell \ layout \ + uconv \ $(NULL) IS_COMPONENT = 1 MODULE_NAME = TransformiixModule @@ -55,10 +56,10 @@ MODULE_NAME = TransformiixModule CPPSRCS = XSLTProcessorModule.cpp LOBJS = ../source/base/Double.$(OBJ_SUFFIX) \ ../source/base/List.$(OBJ_SUFFIX) \ - ../source/base/Map.$(OBJ_SUFFIX) \ ../source/base/SimpleErrorObserver.$(OBJ_SUFFIX) \ ../source/base/txAtoms.$(OBJ_SUFFIX) \ ../source/base/txExpandedNameMap.$(OBJ_SUFFIX) \ + ../source/base/txNamespaceMap.$(OBJ_SUFFIX) \ ../source/base/txURIUtils.$(OBJ_SUFFIX) \ ../source/xml/dom/mozImpl/MozillaAttr.$(OBJ_SUFFIX) \ ../source/xml/dom/mozImpl/MozillaDocument.$(OBJ_SUFFIX) \ @@ -107,18 +108,24 @@ LOBJS = ../source/base/Double.$(OBJ_SUFFIX) \ ../source/xml/parser/txXMLParser.$(OBJ_SUFFIX) \ ../source/xslt/txBufferingHandler.$(OBJ_SUFFIX) \ ../source/xslt/txOutputFormat.$(OBJ_SUFFIX) \ - ../source/xslt/ProcessorState.$(OBJ_SUFFIX) \ + ../source/xslt/txExecutionState.$(OBJ_SUFFIX) \ + ../source/xslt/txInstructions.$(OBJ_SUFFIX) \ + ../source/xslt/txMozillaStylesheetCompiler.$(OBJ_SUFFIX) \ ../source/xslt/txMozillaTextOutput.$(OBJ_SUFFIX) \ ../source/xslt/txMozillaXSLTProcessor.$(OBJ_SUFFIX) \ ../source/xslt/txMozillaXMLOutput.$(OBJ_SUFFIX) \ ../source/xslt/txRtfHandler.$(OBJ_SUFFIX) \ + ../source/xslt/txStylesheet.$(OBJ_SUFFIX) \ + ../source/xslt/txStylesheetCompileHandlers.$(OBJ_SUFFIX) \ + ../source/xslt/txStylesheetCompiler.$(OBJ_SUFFIX) \ ../source/xslt/txTextHandler.$(OBJ_SUFFIX) \ + ../source/xslt/txToplevelItems.$(OBJ_SUFFIX) \ ../source/xslt/txUnknownHandler.$(OBJ_SUFFIX) \ ../source/xslt/txXSLTNumber.$(OBJ_SUFFIX) \ ../source/xslt/txXSLTNumberCounters.$(OBJ_SUFFIX) \ ../source/xslt/txXSLTPatterns.$(OBJ_SUFFIX) \ + ../source/xslt/txXSLTProcessor.$(OBJ_SUFFIX) \ ../source/xslt/txPatternParser.$(OBJ_SUFFIX) \ - ../source/xslt/XSLTProcessor.$(OBJ_SUFFIX) \ ../source/xslt/functions/CurrentFunctionCall.$(OBJ_SUFFIX) \ ../source/xslt/functions/DocumentFunctionCall.$(OBJ_SUFFIX) \ ../source/xslt/functions/ElementAvailableFnCall.$(OBJ_SUFFIX) \ diff --git a/mozilla/extensions/transformiix/build/XSLTProcessorModule.cpp b/mozilla/extensions/transformiix/build/XSLTProcessorModule.cpp index 141ea75d0ee..f41b4c2c351 100755 --- a/mozilla/extensions/transformiix/build/XSLTProcessorModule.cpp +++ b/mozilla/extensions/transformiix/build/XSLTProcessorModule.cpp @@ -42,6 +42,7 @@ #include "nsCRT.h" #include "nsIScriptSecurityManager.h" #include "txURIUtils.h" +#include "txXSLTProcessor.h" #include "nsXPath1Scheme.h" NS_GENERIC_FACTORY_CONSTRUCTOR(nsXPath1SchemeProcessor) @@ -202,7 +203,7 @@ Initialize(nsIModule* aSelf) xs->RegisterExceptionProvider(gXPathExceptionProvider, NS_ERROR_MODULE_DOM_XPATH); - if (!txXSLTProcessor::txInit()) { + if (!txXSLTProcessor::init()) { return NS_ERROR_OUT_OF_MEMORY; } @@ -219,8 +220,6 @@ Initialize(nsIModule* aSelf) return rv; } - TX_LG_CREATE; - return NS_OK; } @@ -249,12 +248,10 @@ Shutdown(nsIModule* aSelf) NS_IF_RELEASE(NS_CLASSINFO_NAME(XPathNSResolver)); NS_IF_RELEASE(NS_CLASSINFO_NAME(XPathResult)); - txXSLTProcessor::txShutdown(); + txXSLTProcessor::shutdown(); NS_IF_RELEASE(gTxSecurityManager); NS_IF_RELEASE(gTxNameSpaceManager); - - TX_LG_DELETE; } // Component Table diff --git a/mozilla/extensions/transformiix/macbuild/transformiix.xml b/mozilla/extensions/transformiix/macbuild/transformiix.xml index f32b6afb929..d9a9ce8083b 100644 --- a/mozilla/extensions/transformiix/macbuild/transformiix.xml +++ b/mozilla/extensions/transformiix/macbuild/transformiix.xml @@ -1069,13 +1069,6 @@ Text - - Name - ProcessorState.cpp - MacOS - Text - - Name ExprLexer.cpp @@ -1307,13 +1300,6 @@ Text - - Name - XSLTProcessor.cpp - MacOS - Text - - Name txXMLParser.cpp @@ -1363,13 +1349,6 @@ Text - - Name - Map.cpp - MacOS - Text - - Name XSLTProcessorModule.cpp @@ -1531,6 +1510,69 @@ Text + + Name + txNamespaceMap.cpp + MacOS + Text + Debug + + + Name + txExecutionState.cpp + MacOS + Text + Debug + + + Name + txInstructions.cpp + MacOS + Text + Debug + + + Name + txStylesheet.cpp + MacOS + Text + Debug + + + Name + txStylesheetCompileHandlers.cpp + MacOS + Text + Debug + + + Name + txStylesheetCompiler.cpp + MacOS + Text + Debug + + + Name + txToplevelItems.cpp + MacOS + Text + Debug + + + Name + txXSLTProcessor.cpp + MacOS + Text + Debug + + + Name + txMozillaStylesheetCompiler.cpp + MacOS + Text + Debug + @@ -1603,11 +1645,6 @@ NodeSet.cpp MacOS - - Name - ProcessorState.cpp - MacOS - Name ExprLexer.cpp @@ -1763,11 +1800,6 @@ MozillaAttr.cpp MacOS - - Name - XSLTProcessor.cpp - MacOS - Name MozillaDocument.cpp @@ -1828,11 +1860,6 @@ FunctionAvailableFnCall.cpp MacOS - - Name - Map.cpp - MacOS - Name XSLTProcessorModule.cpp @@ -1943,6 +1970,51 @@ txUnknownHandler.cpp MacOS + + Name + txNamespaceMap.cpp + MacOS + + + Name + txExecutionState.cpp + MacOS + + + Name + txInstructions.cpp + MacOS + + + Name + txStylesheet.cpp + MacOS + + + Name + txStylesheetCompileHandlers.cpp + MacOS + + + Name + txStylesheetCompiler.cpp + MacOS + + + Name + txToplevelItems.cpp + MacOS + + + Name + txXSLTProcessor.cpp + MacOS + + + Name + txMozillaStylesheetCompiler.cpp + MacOS + @@ -2905,13 +2977,6 @@ Text - - Name - ProcessorState.cpp - MacOS - Text - - Name ExprLexer.cpp @@ -3143,13 +3208,6 @@ Text - - Name - XSLTProcessor.cpp - MacOS - Text - - Name NSPR20.shlb @@ -3227,13 +3285,6 @@ Text - - Name - Map.cpp - MacOS - Text - - Name XSLTProcessorModule.cpp @@ -3423,6 +3474,69 @@ Text Debug + + Name + txNamespaceMap.cpp + MacOS + Text + Debug + + + Name + txExecutionState.cpp + MacOS + Text + Debug + + + Name + txInstructions.cpp + MacOS + Text + Debug + + + Name + txStylesheet.cpp + MacOS + Text + Debug + + + Name + txStylesheetCompileHandlers.cpp + MacOS + Text + Debug + + + Name + txStylesheetCompiler.cpp + MacOS + Text + Debug + + + Name + txToplevelItems.cpp + MacOS + Text + Debug + + + Name + txXSLTProcessor.cpp + MacOS + Text + Debug + + + Name + txMozillaStylesheetCompiler.cpp + MacOS + Text + Debug + @@ -3455,11 +3569,6 @@ NodeSet.cpp MacOS - - Name - ProcessorState.cpp - MacOS - Name ExprLexer.cpp @@ -3615,11 +3724,6 @@ MozillaAttr.cpp MacOS - - Name - XSLTProcessor.cpp - MacOS - Name MozillaDocument.cpp @@ -3700,11 +3804,6 @@ FunctionAvailableFnCall.cpp MacOS - - Name - Map.cpp - MacOS - Name XSLTProcessorModule.cpp @@ -3835,6 +3934,51 @@ txUnknownHandler.cpp MacOS + + Name + txNamespaceMap.cpp + MacOS + + + Name + txExecutionState.cpp + MacOS + + + Name + txInstructions.cpp + MacOS + + + Name + txStylesheet.cpp + MacOS + + + Name + txStylesheetCompileHandlers.cpp + MacOS + + + Name + txStylesheetCompiler.cpp + MacOS + + + Name + txToplevelItems.cpp + MacOS + + + Name + txXSLTProcessor.cpp + MacOS + + + Name + txMozillaStylesheetCompiler.cpp + MacOS + @@ -3859,12 +4003,6 @@ List.cpp MacOS - - transformiixDebug.shlb - Name - Map.cpp - MacOS - transformiixDebug.shlb Name @@ -3883,6 +4021,12 @@ txExpandedNameMap.cpp MacOS + + transformiixDebug.shlb + Name + txNamespaceMap.cpp + MacOS + transformiixDebug.shlb Name @@ -4166,7 +4310,19 @@ transformiixDebug.shlb Name - ProcessorState.cpp + txExecutionState.cpp + MacOS + + + transformiixDebug.shlb + Name + txInstructions.cpp + MacOS + + + transformiixDebug.shlb + Name + txMozillaStylesheetCompiler.cpp MacOS @@ -4205,12 +4361,36 @@ txRtfHandler.cpp MacOS + + transformiixDebug.shlb + Name + txStylesheet.cpp + MacOS + + + transformiixDebug.shlb + Name + txStylesheetCompileHandlers.cpp + MacOS + + + transformiixDebug.shlb + Name + txStylesheetCompiler.cpp + MacOS + transformiixDebug.shlb Name txTextHandler.cpp MacOS + + transformiixDebug.shlb + Name + txToplevelItems.cpp + MacOS + transformiixDebug.shlb Name @@ -4238,7 +4418,7 @@ transformiixDebug.shlb Name - XSLTProcessor.cpp + txXSLTProcessor.cpp MacOS functions diff --git a/mozilla/extensions/transformiix/source/base/List.h b/mozilla/extensions/transformiix/source/base/List.h index e1bff240f2b..bc4093c4449 100644 --- a/mozilla/extensions/transformiix/source/base/List.h +++ b/mozilla/extensions/transformiix/source/base/List.h @@ -105,6 +105,7 @@ protected: ListItem* remove(ListItem* sItem); private: + txList(const txList& aOther); // not implemented ListItem* firstItem; ListItem* lastItem; diff --git a/mozilla/extensions/transformiix/source/base/Makefile.in b/mozilla/extensions/transformiix/source/base/Makefile.in index cd13b3ce5c4..a947592e7fc 100644 --- a/mozilla/extensions/transformiix/source/base/Makefile.in +++ b/mozilla/extensions/transformiix/source/base/Makefile.in @@ -44,10 +44,10 @@ endif CPPSRCS = Double.cpp \ List.cpp \ - Map.cpp \ SimpleErrorObserver.cpp \ txAtoms.cpp \ txExpandedNameMap.cpp \ + txNamespaceMap.cpp \ txURIUtils.cpp ifdef TX_EXE diff --git a/mozilla/extensions/transformiix/source/base/Map.cpp b/mozilla/extensions/transformiix/source/base/Map.cpp deleted file mode 100644 index 9c4e6472d67..00000000000 --- a/mozilla/extensions/transformiix/source/base/Map.cpp +++ /dev/null @@ -1,270 +0,0 @@ -/* - * 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 XSL:P XSLT processor. - * - * The Initial Developer of the Original Code is Keith Visco. - * - * Portions created by Keith Visco (C) 1999-2000 Keith Visco. - * All Rights Reserved. - * - * Contributor(s): - * Keith Visco, kvisco@ziplink.net - * -- original author. - * - */ - -/* - * A Hashtable for TxObjects - */ - - -#include "Map.h" -#include "List.h" - - //-------------/ - //- Constants -/ -//-------------/ - -const int Map::DEFAULT_SIZE = 13; - - //----------------/ - //- Constructors -/ -//----------------/ - -/** - * Creates a new Map with the default Size -**/ -Map::Map() { - initialize(DEFAULT_SIZE); -} //-- Map - -/** - * Creates a new Map with the specified number of buckets -**/ -Map::Map(int size) { - initialize(size); -} //-- Map - -/** - * Helper method for Constructors -**/ -void Map::initialize(PRInt32 size) { - - //-- by default the Map will not delete it's - //-- object references - mOwnership = eOwnsNone; - - //-- create a new array of bucket pointers - elements = new BucketItem*[size]; - - //-- initialize all elements to 0; - for ( PRInt32 i = 0; i < size; i++ ) elements[i] = 0; - - numberOfBuckets = size; - numberOfElements = 0; -} //-- initialize - -/** - * Destructor for Map -**/ -Map::~Map() { - clear(); - delete [] elements; -} //-- ~Map - - - -/** - * Removes all elements from the Map. Deletes objects according - * to the mOwnership attribute -**/ -void Map::clear() { - - for (int i = 0; i < numberOfBuckets; i++) { - - BucketItem* bktItem = elements[i]; - while (bktItem) { - BucketItem* tItem = bktItem; - bktItem = bktItem->next; - if (mOwnership & eOwnsItems) - delete tItem->item; - if (mOwnership & eOwnsKeys) - delete tItem->key; - //--delete tItem; - delete tItem; - } - } - numberOfElements = 0; -} //-- clear - -/** - * Returns the object reference in this Map associated with the given key - * @return the object reference in this Map associated with the given key -**/ -TxObject* Map::get(TxObject* key) { - BucketItem* item = getBucketItem(key); - if ( item ) return item->item; - return 0; -} //-- get - -/** - * Returns true if there are no objects in this map. - * @return true if there are no objects in this map. -**/ -MBool Map::isEmpty() { - return (numberOfElements == 0) ? MB_TRUE : MB_FALSE; -} //-- isEmpty - - -/** - * Returns a List of all the keys in this Map. - * Please delete this List when you are done with it -**/ -List* Map::keys() { - List* list = new List(); - for (int i = 0; i < numberOfBuckets; i++) { - BucketItem* item = elements[i]; - while (item) { - list->add(item->key); - item = item->next; - } - } - return list; -} //-- keys - -/** - * Adds the TxObject reference to the map and associates it with the given - * key -**/ -void Map::put(TxObject* key, TxObject* obj) { - - if ((!key) || (!obj)) return; - - //-- compute hash for key - PRUint32 hashCode = key->hashCode(); - - //-- calculate index - int idx = hashCode % numberOfBuckets; - - //-- fetch first item in bucket - BucketItem* bktItem = elements[idx]; - - //-- if bktItem is 0 then there are no items is this Bucket, - //-- add to front of list - if ( !bktItem ) { - elements[idx] = createBucketItem(key, obj); - ++numberOfElements; - } - //-- find current item, or add to end of list - else { - BucketItem* prevItem = bktItem; - //-- advance to next spot - while ( bktItem ) { - //-- if current key equals desired key, break - if ( bktItem->key->equals(key) ) { - break; - } - prevItem = bktItem; - bktItem = bktItem->next; - } - //-- if we did not find a bucket Item create a new one - if ( !bktItem) { - bktItem = createBucketItem(key, obj); - prevItem->next = bktItem; - bktItem->prev = prevItem; - ++numberOfElements; - } - //-- we found bucket item, just set value - else bktItem->item = obj; - } -} //-- put -/** - * Removes the the specified TxObject from the Map - * @param key the TxObject which is used to calculate the hashCode of - * the TxObject to remove from the Map - * @return the TxObject removed from the Map -**/ -TxObject* Map::remove(TxObject* key) { - - if (!key) return 0; - - // compute hash for key - PRUint32 hashCode = key->hashCode(); - - int idx = hashCode % numberOfBuckets; - - BucketItem* bktItem = elements[idx]; - - while ( bktItem ) { - if ( bktItem->key->equals(key) ) break; - bktItem = bktItem->next; - } - - if ( bktItem ) { - if (bktItem == elements[idx]) elements[idx] = bktItem->next; - else bktItem->prev->next = bktItem->next; - numberOfElements--; - TxObject* txObject = bktItem->item; - bktItem->item = 0; - delete bktItem; - return txObject; - } - return 0; - -} //-- remove - -/** - * Sets the ownership flag. -**/ -void Map::setOwnership(txMapOwnership aOwnership) { - mOwnership = aOwnership; -} //-- setOwnership - -/** - * Returns the number of key-object pairs in the Map - * @return the number of key-object pairs in the Map -**/ -int Map::size() { - return numberOfElements; -} //-- size - - //-------------------/ - //- Private Methods -/ -//-------------------/ - -Map::BucketItem* Map::createBucketItem(TxObject* key, TxObject* obj) -{ - BucketItem* bktItem = new BucketItem; - bktItem->next = 0; - bktItem->prev = 0; - bktItem->key = key; - bktItem->item = obj; - return bktItem; -} //-- createBucketItem - -Map::BucketItem* Map::getBucketItem(TxObject* key) { - - // compute hash for key - PRUint32 hashCode = key->hashCode(); - - int idx = hashCode % numberOfBuckets; - - BucketItem* bktItem = elements[idx]; - - while ( bktItem ) { - if ( bktItem->key->equals(key) ) return bktItem; - bktItem = bktItem->next; - } - - return bktItem; - -} //-- getBucketItem diff --git a/mozilla/extensions/transformiix/source/base/Map.h b/mozilla/extensions/transformiix/source/base/Map.h deleted file mode 100644 index 70211499367..00000000000 --- a/mozilla/extensions/transformiix/source/base/Map.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - * 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 XSL:P XSLT processor. - * - * The Initial Developer of the Original Code is Keith Visco. - * - * Portions created by Keith Visco (C) 1999-2000 Keith Visco. - * All Rights Reserved. - * - * Contributor(s): - * Keith Visco, kvisco@ziplink.net - * -- original author. - * - */ - -/* - * A Hashtable for TxObjects - */ - -#ifndef TRANSFRMX_MAP_H -#define TRANSFRMX_MAP_H - -#include "baseutils.h" -#include "TxObject.h" - -class txList; - -class Map : public TxObject { - - -public: - - //----------------/ - //- Constructors -/ - //----------------/ - - /** - * Creates a new Map with the default Size - **/ - Map(); - - /** - * Creates a new Map with the specified number of buckets - **/ - Map(int size); - - /** - * Destructor for a Map table, will not delete references unless - * The setObjectDeletion flag has been set to MB_TRUE - **/ - virtual ~Map(); - - - /** - * Returns a list of all the keys of this Map. - * - * You will need to delete this List when you are done with it. - **/ - txList* keys(); - - /** - * Returns the object reference in this Map associated with the given name - * @return the object reference in this Map associated with the given name - **/ - TxObject* get(TxObject* key); - - /** - * Adds the TxObject reference to the map and associates it with the given - * key - **/ - void put(TxObject* key, TxObject* obj); - - /** - * enum used when setting ownership - **/ - enum txMapOwnership - { - eOwnsNone = 0x00, - eOwnsItems = 0x01, - eOwnsKeys = 0x02, - eOwnsKeysAndItems = eOwnsItems | eOwnsKeys - }; - - /** - * Removes all elements from the Map. Deletes objects according - * to the mOwnership attribute - **/ - void clear(); - - /** - * Returns true if there are no elements in this Map - * @return true if there are no elements in this Map. - **/ - MBool isEmpty(); - - // THIS IS DEPRECATED - TxObject* remove(TxObject* key); - - // THIS IS DEPRECATED, use setOwnership - void setObjectDeletion(MBool deleteObjects) - { - setOwnership(deleteObjects ? eOwnsKeysAndItems : eOwnsNone ); - } - - /** - * Sets the ownership attribute. - **/ - void setOwnership(txMapOwnership aOwnership); - - /** - * Returns the number of key-element pairs in the Map - * @return the number of key-element in the Map - **/ - int size(); - - //-------------------/ - //- Private Members -/ - //-------------------/ - - -private: - - struct BucketItem { - TxObject* key; - TxObject* item; - BucketItem* next; - BucketItem* prev; - }; - - static const int DEFAULT_SIZE; - - // map table - BucketItem** elements; - - PRInt32 numberOfBuckets; - PRInt32 numberOfElements; - - /** - * The ownership flag. Used to decide which objects are - * owned by the map and thus should be deleted when released - **/ - txMapOwnership mOwnership; - - //-------------------/ - //- Private Methods -/ - //-------------------/ - - BucketItem* createBucketItem(TxObject* key, TxObject* objPtr); - - BucketItem* getBucketItem(TxObject* key); - - /** - * Helper method for constructors - **/ - void initialize(int size); - -}; - -#endif diff --git a/mozilla/extensions/transformiix/source/base/txError.h b/mozilla/extensions/transformiix/source/base/txError.h index 9f1a86101c0..6a378188058 100644 --- a/mozilla/extensions/transformiix/source/base/txError.h +++ b/mozilla/extensions/transformiix/source/base/txError.h @@ -51,4 +51,34 @@ #define NS_ERROR_XPATH_INVALID_ARG NS_ERROR_INVALID_ARG #define NS_ERROR_XSLT_INVALID_URL NS_ERROR_INVALID_ARG +#define NS_ERROR_XSLT_PARSE_FAILURE \ + NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XSLT, 1) + +#define NS_ERROR_XPATH_PARSE_FAILURE \ + NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XSLT, 2) + +#define NS_ERROR_XSLT_GET_NEW_HANDLER \ + NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XSLT, 3) + +#define NS_ERROR_XSLT_ALREADY_SET \ + NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XSLT, 4) + +#define NS_ERROR_XSLT_EXECUTION_FAILURE \ + NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XSLT, 5) + +#define NS_ERROR_XPATH_UNKNOWN_FUNCTION \ + NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XSLT, 6) + +#define NS_ERROR_XSLT_BAD_RECURSION \ + NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XSLT, 7) + +#define NS_ERROR_XSLT_BAD_VALUE \ + NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XSLT, 8) + +#define NS_ERROR_XSLT_NODESET_EXPECTED \ + NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XSLT, 9) + +#define NS_ERROR_XSLT_ABORTED \ + NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XSLT, 10) + #endif // __TX_ERROR diff --git a/mozilla/extensions/transformiix/source/base/txExpandedNameMap.cpp b/mozilla/extensions/transformiix/source/base/txExpandedNameMap.cpp index 3b71a912911..fca48ce8cea 100644 --- a/mozilla/extensions/transformiix/source/base/txExpandedNameMap.cpp +++ b/mozilla/extensions/transformiix/source/base/txExpandedNameMap.cpp @@ -65,7 +65,7 @@ nsresult txExpandedNameMap::add(const txExpandedName& aKey, TxObject* aValue) for (i = 0; i < mItemCount; ++i) { if (mItems[i].mLocalName == aKey.mLocalName && mItems[i].mNamespaceID == aKey.mNamespaceID) { - return NS_ERROR_FAILURE; + return NS_ERROR_XSLT_ALREADY_SET; } } @@ -142,7 +142,7 @@ nsresult txExpandedNameMap::set(const txExpandedName& aKey, TxObject* aValue) * @param aKey key for item to get * @return item with specified key, or null if no such item exists */ -TxObject* txExpandedNameMap::get(const txExpandedName& aKey) +TxObject* txExpandedNameMap::get(const txExpandedName& aKey) const { int i; for (i = 0; i < mItemCount; ++i) { diff --git a/mozilla/extensions/transformiix/source/base/txExpandedNameMap.h b/mozilla/extensions/transformiix/source/base/txExpandedNameMap.h index 66388b84f78..295a53a43bc 100644 --- a/mozilla/extensions/transformiix/source/base/txExpandedNameMap.h +++ b/mozilla/extensions/transformiix/source/base/txExpandedNameMap.h @@ -73,7 +73,7 @@ public: * @param aKey key for item to get * @return item with specified key, or null if no such item exists */ - TxObject* get(const txExpandedName& aKey); + TxObject* get(const txExpandedName& aKey) const; /** * Removes an item, deleting it if the map owns the values diff --git a/mozilla/extensions/transformiix/source/base/txNamespaceMap.cpp b/mozilla/extensions/transformiix/source/base/txNamespaceMap.cpp new file mode 100644 index 00000000000..3ca336b960b --- /dev/null +++ b/mozilla/extensions/transformiix/source/base/txNamespaceMap.cpp @@ -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 + * Jonas Sicking. + * Portions created by the Initial Developer are Copyright (C) 2002 + * Jonas Sicking. All Rights Reserved. + * + * Contributor(s): + * Jonas Sicking + * + * 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 "txNamespaceMap.h" +#include "dom.h" +#include "txAtoms.h" + +txNamespaceMap::txNamespaceMap() +{ +} + +txNamespaceMap::txNamespaceMap(const txNamespaceMap& aOther) + : mPrefixes(aOther.mPrefixes) +{ + mNamespaces = aOther.mNamespaces; //bah! I want a copy-constructor! +} + +nsresult +txNamespaceMap::addNamespace(nsIAtom* aPrefix, const nsAString& aNamespaceURI) +{ + nsIAtom* prefix = aPrefix == txXMLAtoms::_empty ? 0 : aPrefix; + + PRInt32 nsId; + if (!prefix && aNamespaceURI.IsEmpty()) { + nsId = kNameSpaceID_None; + } + else { +#ifdef TX_EXE + nsId = txNamespaceManager::getNamespaceID(aNamespaceURI); +#else + NS_ASSERTION(gTxNameSpaceManager, "No namespace manager"); + gTxNameSpaceManager->RegisterNameSpace(aNamespaceURI, nsId); +#endif + } + + // Check if the mapping already exists + PRInt32 index = mPrefixes.IndexOf(prefix); + if (index >= 0) { + mNamespaces.ReplaceElementAt(NS_INT32_TO_PTR(nsId), index); + + return NS_OK; + } + + // New mapping + if (!mPrefixes.AppendObject(prefix)) { + return NS_ERROR_OUT_OF_MEMORY; + } + + if (!mNamespaces.AppendElement(NS_INT32_TO_PTR(nsId))) { + mPrefixes.RemoveObjectAt(mPrefixes.Count() - 1); + + return NS_ERROR_OUT_OF_MEMORY; + } + + return NS_OK; +} + +PRInt32 +txNamespaceMap::lookupNamespace(nsIAtom* aPrefix) +{ + if (aPrefix == txXMLAtoms::xml) { + return kNameSpaceID_XML; + } + + nsIAtom* prefix = aPrefix == txXMLAtoms::_empty ? 0 : aPrefix; + + PRInt32 index = mPrefixes.IndexOf(prefix); + if (index >= 0) { + return NS_PTR_TO_INT32(mNamespaces.SafeElementAt(index)); + } + + if (!prefix) { + return kNameSpaceID_None; + } + + return kNameSpaceID_Unknown; +} + +PRInt32 +txNamespaceMap::lookupNamespace(const nsAString& aPrefix) +{ + nsCOMPtr prefix = do_GetAtom(aPrefix); + + return lookupNamespace(prefix); +} + +PRInt32 +txNamespaceMap::lookupNamespaceWithDefault(const nsAString& aPrefix) +{ + nsCOMPtr prefix = do_GetAtom(aPrefix); + if (prefix != txXSLTAtoms::_poundDefault) { + return lookupNamespace(prefix); + } + + return lookupNamespace(nsnull); +} diff --git a/mozilla/extensions/transformiix/source/base/txNamespaceMap.h b/mozilla/extensions/transformiix/source/base/txNamespaceMap.h new file mode 100644 index 00000000000..8ecb1cd0a8d --- /dev/null +++ b/mozilla/extensions/transformiix/source/base/txNamespaceMap.h @@ -0,0 +1,78 @@ +/* -*- 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 + * Jonas Sicking. + * Portions created by the Initial Developer are Copyright (C) 2002 + * Jonas Sicking. All Rights Reserved. + * + * Contributor(s): + * Jonas Sicking + * + * 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_TXNAMESPACEMAP_H +#define TRANSFRMX_TXNAMESPACEMAP_H + +#include "txError.h" +#include "baseutils.h" +#include "nsIAtom.h" +#include "nsCOMArray.h" + +class txNamespaceMap +{ +public: + txNamespaceMap(); + txNamespaceMap(const txNamespaceMap& aOther); + + nsrefcnt AddRef() + { + return ++mRefCnt; + } + nsrefcnt Release() + { + if (--mRefCnt == 0) { + mRefCnt = 1; //stabilize + delete this; + return 0; + } + return mRefCnt; + } + + nsresult addNamespace(nsIAtom* aPrefix, const nsAString& aNamespaceURI); + PRInt32 lookupNamespace(nsIAtom* aPrefix); + PRInt32 lookupNamespace(const nsAString& aPrefix); + PRInt32 lookupNamespaceWithDefault(const nsAString& aPrefix); + +private: + nsAutoRefCnt mRefCnt; + nsCOMArray mPrefixes; + nsVoidArray mNamespaces; +}; + +#endif //TRANSFRMX_TXNAMESPACEMAP_H diff --git a/mozilla/extensions/transformiix/source/lib/Makefile.in b/mozilla/extensions/transformiix/source/lib/Makefile.in index 81d46c9367b..4af9300585c 100644 --- a/mozilla/extensions/transformiix/source/lib/Makefile.in +++ b/mozilla/extensions/transformiix/source/lib/Makefile.in @@ -36,10 +36,10 @@ REQUIRES = string \ OBJS = ../base/Double.$(OBJ_SUFFIX) \ ../base/List.$(OBJ_SUFFIX) \ - ../base/Map.$(OBJ_SUFFIX) \ ../base/SimpleErrorObserver.$(OBJ_SUFFIX) \ ../base/txAtoms.$(OBJ_SUFFIX) \ ../base/txExpandedNameMap.$(OBJ_SUFFIX) \ + ../base/txNamespaceMap.$(OBJ_SUFFIX) \ ../base/txStringUtils.$(OBJ_SUFFIX) \ ../base/txURIUtils.$(OBJ_SUFFIX) \ ../xml/dom/standalone/Attr.$(OBJ_SUFFIX) \ @@ -82,21 +82,27 @@ OBJS = ../base/Double.$(OBJ_SUFFIX) \ ../xml/XMLUtils.$(OBJ_SUFFIX) \ ../xml/XMLDOMUtils.$(OBJ_SUFFIX) \ ../xml/parser/txXMLParser.$(OBJ_SUFFIX) \ - ../xslt/txOutputFormat.$(OBJ_SUFFIX) \ - ../xslt/ProcessorState.$(OBJ_SUFFIX) \ ../xslt/txBufferingHandler.$(OBJ_SUFFIX) \ + ../xslt/txExecutionState.$(OBJ_SUFFIX) \ ../xslt/txHTMLOutput.$(OBJ_SUFFIX) \ + ../xslt/txInstructions.$(OBJ_SUFFIX) \ + ../xslt/txOutputFormat.$(OBJ_SUFFIX) \ ../xslt/txRtfHandler.$(OBJ_SUFFIX) \ + ../xslt/txStandaloneXSLTProcessor.$(OBJ_SUFFIX) \ + ../xslt/txStandaloneStylesheetCompiler.$(OBJ_SUFFIX) \ + ../xslt/txStylesheet.$(OBJ_SUFFIX) \ + ../xslt/txStylesheetCompileHandlers.$(OBJ_SUFFIX) \ + ../xslt/txStylesheetCompiler.$(OBJ_SUFFIX) \ ../xslt/txTextHandler.$(OBJ_SUFFIX) \ ../xslt/txTextOutput.$(OBJ_SUFFIX) \ + ../xslt/txToplevelItems.$(OBJ_SUFFIX) \ ../xslt/txUnknownHandler.$(OBJ_SUFFIX) \ ../xslt/txXMLOutput.$(OBJ_SUFFIX) \ ../xslt/txXSLTNumber.$(OBJ_SUFFIX) \ ../xslt/txXSLTNumberCounters.$(OBJ_SUFFIX) \ ../xslt/txXSLTPatterns.$(OBJ_SUFFIX) \ ../xslt/txPatternParser.$(OBJ_SUFFIX) \ - ../xslt/XSLTProcessor.$(OBJ_SUFFIX) \ - ../xslt/txStandaloneXSLTProcessor.$(OBJ_SUFFIX) \ + ../xslt/txXSLTProcessor.$(OBJ_SUFFIX) \ ../xslt/functions/CurrentFunctionCall.$(OBJ_SUFFIX) \ ../xslt/functions/DocumentFunctionCall.$(OBJ_SUFFIX) \ ../xslt/functions/ElementAvailableFnCall.$(OBJ_SUFFIX) \ @@ -121,3 +127,4 @@ INCLUDES += -I$(srcdir)/../xslt -I$(srcdir)/../base -I$(srcdir)/../net \ -I$(srcdir)/../xml/parser \ -I$(srcdir)/../xpath -I$(srcdir)/../xslt/util \ -I$(srcdir)/../xslt/functions $(MARK_INC) +DEFINES += -DXML_DTD -DXML_UNICODE diff --git a/mozilla/extensions/transformiix/source/main/testXalan.cpp b/mozilla/extensions/transformiix/source/main/testXalan.cpp index 28f4cec81ed..35443fa04f7 100644 --- a/mozilla/extensions/transformiix/source/main/testXalan.cpp +++ b/mozilla/extensions/transformiix/source/main/testXalan.cpp @@ -259,7 +259,7 @@ void runCategory(nsIFile* aConfCat, nsIFile* aGoldCat, nsIFile* aRefTmp, aRefTmp->GetFileSize(&resultSize); reference->GetFileSize(&refSize); result.seekg(0); - int read, toread = (int)resultSize; + int toread = (int)resultSize; nsCString resContent, refContent; resContent.SetCapacity(toread); readToString(result, resContent); @@ -344,7 +344,7 @@ int main(int argc, char** argv) } } - if (!txXSLTProcessor::txInit()) { + if (!txXSLTProcessor::init()) { PRBool exists; if (NS_SUCCEEDED(resFile->Exists(&exists)) && exists) resFile->Remove(PR_FALSE); @@ -408,7 +408,7 @@ int main(int argc, char** argv) if (NS_SUCCEEDED(resFile->Exists(&exists)) && exists) resFile->Remove(PR_FALSE); resultFileStream.close(); - txXSLTProcessor::txShutdown(); + txXSLTProcessor::shutdown(); rv = NS_ShutdownXPCOM(nsnull); #ifdef NS_TRACE_MALLOC NS_TraceMallocShutdown(); diff --git a/mozilla/extensions/transformiix/source/main/transformiix.cpp b/mozilla/extensions/transformiix/source/main/transformiix.cpp index 32f14e3df90..16523ff3df7 100644 --- a/mozilla/extensions/transformiix/source/main/transformiix.cpp +++ b/mozilla/extensions/transformiix/source/main/transformiix.cpp @@ -124,7 +124,7 @@ int main(int argc, char** argv) rv = NS_InitXPCOM2(nsnull, nsnull, nsnull); NS_ENSURE_SUCCESS(rv, rv); - if (!txXSLTProcessor::txInit()) + if (!txXSLTProcessor::init()) return 1; txOptions options; @@ -189,7 +189,7 @@ int main(int argc, char** argv) } resultFileStream.close(); - txXSLTProcessor::txShutdown(); + txXSLTProcessor::shutdown(); rv = NS_ShutdownXPCOM(nsnull); NS_ENSURE_SUCCESS(rv, rv); return 0; diff --git a/mozilla/extensions/transformiix/source/main/txXSLTMarkDriver.cpp b/mozilla/extensions/transformiix/source/main/txXSLTMarkDriver.cpp index bb2ce99f844..2a45147eb2b 100644 --- a/mozilla/extensions/transformiix/source/main/txXSLTMarkDriver.cpp +++ b/mozilla/extensions/transformiix/source/main/txXSLTMarkDriver.cpp @@ -43,6 +43,7 @@ * See http://www.datapower.com/XSLTMark/ */ +#include "txStandaloneStylesheetCompiler.h" #include "txStandaloneXSLTProcessor.h" #include "nsXPCOM.h" #include "xmExternalDriver.hpp" @@ -51,15 +52,16 @@ class txDriverProcessor : public txStandaloneXSLTProcessor, public xmExternalDriver { public: - txDriverProcessor() : mXSL(0), mXML(0), mOut(0) + txDriverProcessor() : mXML(0), mOut(0) { } int loadStylesheet (char * filename) { - delete mXSL; - mXSL = parsePath(nsDependentCString(filename), mObserver); - return mXSL ? 0 : 1; + NS_ConvertASCIItoUCS2 path(filename); + nsresult rv = + TX_CompileStylesheetPath(path, getter_AddRefs(mStylesheet)); + return NS_SUCCEEDED(rv) ? 0 : 1; } int setInputDocument (char * filename) { @@ -74,7 +76,9 @@ public: } int runTransform () { - nsresult rv = transform(mXML, mXSL, *mOut, mObserver); + if (!mXML || !mStylesheet || !mOut) + return 1; + nsresult rv = transform(mXML, mStylesheet, *mOut, mObserver); return NS_FAILED(rv); } int closeOutput () @@ -87,8 +91,6 @@ public: } int terminate() { - delete mXSL; - mXSL = 0; delete mXML; mXML = 0; if (mOut && mOut->is_open()) @@ -99,12 +101,12 @@ public: } ~txDriverProcessor() { - delete mXSL; delete mXML; delete mOut; } private: - Document *mXSL, *mXML; + Document *mXML; + nsRefPtr mStylesheet; SimpleErrorObserver mObserver; ofstream* mOut; }; @@ -113,10 +115,10 @@ int main (int argc, char ** argv) { txDriverProcessor driver; NS_InitXPCOM2(nsnull, nsnull, nsnull); - if (!txDriverProcessor::txInit()) + if (!txDriverProcessor::init()) return 1; driver.main (argc, argv); - txDriverProcessor::txShutdown(); + txDriverProcessor::shutdown(); NS_ShutdownXPCOM(nsnull); return 0; } diff --git a/mozilla/extensions/transformiix/source/xml/XMLUtils.cpp b/mozilla/extensions/transformiix/source/xml/XMLUtils.cpp index f4c1cb92d76..db3d87f80b5 100644 --- a/mozilla/extensions/transformiix/source/xml/XMLUtils.cpp +++ b/mozilla/extensions/transformiix/source/xml/XMLUtils.cpp @@ -34,6 +34,7 @@ #include "nsReadableUtils.h" #include "txAtoms.h" #include "txStringUtils.h" +#include "txNamespaceMap.h" /** * Helper class for checking and partioning of QNames @@ -113,11 +114,10 @@ txQNameParser::parse(const nsAString::const_iterator& aStart, return eBrokenName; } -nsresult txExpandedName::init(const nsAString& aQName, - Node* aResolver, - MBool aUseDefault) +nsresult +txExpandedName::init(const nsAString& aQName, txNamespaceMap* aResolver, + MBool aUseDefault) { - NS_ASSERTION(aResolver, "missing resolve node"); nsAString::const_iterator start, end; aQName.BeginReading(start); aQName.EndReading(end); @@ -131,7 +131,7 @@ nsresult txExpandedName::init(const nsAString& aQName, if (qr == txQNameParser::eTwoNames) { nsCOMPtr prefix = do_GetAtom(Substring(start, p.mColon)); - PRInt32 namespaceID = aResolver->lookupNamespaceID(prefix); + PRInt32 namespaceID = aResolver->lookupNamespace(prefix); if (namespaceID == kNameSpaceID_Unknown) return NS_ERROR_FAILURE; mNamespaceID = namespaceID; @@ -141,7 +141,7 @@ nsresult txExpandedName::init(const nsAString& aQName, else { mLocalName = do_GetAtom(aQName); if (aUseDefault) - mNamespaceID = aResolver->lookupNamespaceID(0); + mNamespaceID = aResolver->lookupNamespace(0); else mNamespaceID = kNameSpaceID_None; } @@ -152,6 +152,30 @@ nsresult txExpandedName::init(const nsAString& aQName, //- Implementation of XMLUtils -/ //------------------------------/ +nsresult +XMLUtils::splitXMLName(const nsAString& aName, nsIAtom** aPrefix, + nsIAtom** aLocalName) +{ + nsAString::const_iterator start, end; + aName.BeginReading(start); + aName.EndReading(end); + txQNameParser p; + txQNameParser::QResult qr = p.parse(start, end); + + if (qr == txQNameParser::eBrokenName) { + return NS_ERROR_FAILURE; + } + if (qr == txQNameParser::eTwoNames) { + *aPrefix = NS_NewAtom(Substring(start, p.mColon)); + *aLocalName = NS_NewAtom(Substring(++p.mColon, end)); + } + else { + *aPrefix = nsnull; + *aLocalName = NS_NewAtom(aName); + } + return NS_OK; +} + void XMLUtils::getPrefix(const nsAString& src, nsIAtom** dest) { // Anything preceding ':' is the namespace part of the name diff --git a/mozilla/extensions/transformiix/source/xml/XMLUtils.h b/mozilla/extensions/transformiix/source/xml/XMLUtils.h index 1a1565b0c0c..00440da5b28 100644 --- a/mozilla/extensions/transformiix/source/xml/XMLUtils.h +++ b/mozilla/extensions/transformiix/source/xml/XMLUtils.h @@ -36,6 +36,8 @@ #include "nsIAtom.h" #include "txError.h" +class txNamespaceMap; + class txExpandedName { public: txExpandedName() : mNamespaceID(kNameSpaceID_None) @@ -58,7 +60,19 @@ public: { } - nsresult init(const nsAString& aQName, Node* aResolver, MBool aUseDefault); + nsresult init(const nsAString& aQName, txNamespaceMap* aResolver, + MBool aUseDefault); + + void reset() + { + mNamespaceID = kNameSpaceID_None; + mLocalName = nsnull; + } + + PRBool isNull() + { + return mNamespaceID == kNameSpaceID_None && !mLocalName; + } txExpandedName& operator = (const txExpandedName& rhs) { @@ -86,7 +100,8 @@ public: class XMLUtils { public: - + static nsresult splitXMLName(const nsAString& aName, nsIAtom** aPrefix, + nsIAtom** aLocalName); static void getPrefix(const nsAString& src, nsIAtom** dest); static const nsDependentSubstring getLocalPart(const nsAString& src); static void getLocalPart(const nsAString& src, nsIAtom** dest); diff --git a/mozilla/extensions/transformiix/source/xpath/Expr.h b/mozilla/extensions/transformiix/source/xpath/Expr.h index f816a5d8945..81a42d00df6 100644 --- a/mozilla/extensions/transformiix/source/xpath/Expr.h +++ b/mozilla/extensions/transformiix/source/xpath/Expr.h @@ -41,6 +41,7 @@ #include "nsString.h" #include "nsIAtom.h" #include "TxObject.h" +#include "nsAutoPtr.h" /* XPath class definitions. @@ -343,18 +344,13 @@ public: * @param nodeExpr the NodeExpr to use when matching Nodes * @param axisIdentifier the Axis Identifier in which to search for nodes **/ - LocationStep(txNodeTest* aNodeTest, LocationStepType aAxisIdentifier); - - /** - * Destructor, will delete all predicates and the given NodeExpr - **/ - virtual ~LocationStep(); + LocationStep(nsAutoPtr aNodeTest, LocationStepType aAxisIdentifier); TX_DECL_EXPR; private: - txNodeTest* mNodeTest; + nsAutoPtr mNodeTest; LocationStepType mAxisIdentifier; void fromDescendants(Node* node, txIMatchContext* aContext, diff --git a/mozilla/extensions/transformiix/source/xpath/ExprParser.cpp b/mozilla/extensions/transformiix/source/xpath/ExprParser.cpp index c6740e36761..33edf8eb2cd 100644 --- a/mozilla/extensions/transformiix/source/xpath/ExprParser.cpp +++ b/mozilla/extensions/transformiix/source/xpath/ExprParser.cpp @@ -499,11 +499,10 @@ Expr* ExprParser::createFunctionCall(ExprLexer& lexer, } rv = aContext->resolveFunctionCall(lName, namespaceID, fnCall); - // XXX this should be removed once we don't return - // NS_ERROR_NOT_IMPLEMENTED for unparsed-entity-uri(). As should the - // code in parseParameters that deals with fnCall = 0. - // Bug 65981 - if (rv == NS_ERROR_NOT_IMPLEMENTED) { + // XXX We should have an errorfunction that always fails + // and use that here + if (rv == NS_ERROR_NOT_IMPLEMENTED || + rv == NS_ERROR_XPATH_UNKNOWN_FUNCTION) { NS_ASSERTION(!fnCall, "Now is it implemented or not?"); if (!parseParameters(0, lexer, aContext)) { return 0; @@ -537,7 +536,7 @@ LocationStep* ExprParser::createLocationStep(ExprLexer& lexer, { //-- child axis is default LocationStep::LocationStepType axisIdentifier = LocationStep::CHILD_AXIS; - txNodeTest* nodeTest = 0; + nsAutoPtr nodeTest; //-- get Axis Identifier or AbbreviatedStep, if present Token* tok = lexer.peek(); @@ -677,7 +676,6 @@ LocationStep* ExprParser::createLocationStep(ExprLexer& lexer, LocationStep* lstep = new LocationStep(nodeTest, axisIdentifier); if (!lstep) { //XXX out of memory - delete nodeTest; return 0; } diff --git a/mozilla/extensions/transformiix/source/xpath/FunctionCall.cpp b/mozilla/extensions/transformiix/source/xpath/FunctionCall.cpp index f0c2c262112..f9439d57e20 100644 --- a/mozilla/extensions/transformiix/source/xpath/FunctionCall.cpp +++ b/mozilla/extensions/transformiix/source/xpath/FunctionCall.cpp @@ -126,7 +126,7 @@ NodeSet* FunctionCall::evaluateToNodeSet(Expr* aExpr, txIEvalContext* aContext) return 0; if (exprResult->getResultType() != ExprResult::NODESET) { - aContext->receiveError(NS_LITERAL_STRING("NodeSet expected as argument"), NS_ERROR_XPATH_INVALID_ARG); + aContext->receiveError(NS_LITERAL_STRING("NodeSet expected as argument"), NS_ERROR_XSLT_NODESET_EXPECTED); delete exprResult; return 0; } diff --git a/mozilla/extensions/transformiix/source/xpath/LocationStep.cpp b/mozilla/extensions/transformiix/source/xpath/LocationStep.cpp index 3d88510b25b..dc40f3cfe05 100644 --- a/mozilla/extensions/transformiix/source/xpath/LocationStep.cpp +++ b/mozilla/extensions/transformiix/source/xpath/LocationStep.cpp @@ -36,21 +36,12 @@ * @param nodeExpr the NodeExpr to use when matching Nodes * @param axisIdentifier the Axis Identifier in which to search for nodes **/ -LocationStep::LocationStep(txNodeTest* aNodeTest, +LocationStep::LocationStep(nsAutoPtr aNodeTest, LocationStepType aAxisIdentifier) : mNodeTest(aNodeTest), mAxisIdentifier(aAxisIdentifier) { } //-- LocationStep -/** - * Destroys this LocationStep - * All predicates will be deleted - * The NodeExpr will be deleted -**/ -LocationStep::~LocationStep() { - delete mNodeTest; -} //-- ~LocationStep - //-----------------------------/ //- Virtual methods from Expr -/ //-----------------------------/ diff --git a/mozilla/extensions/transformiix/source/xpath/nsXPathExpression.cpp b/mozilla/extensions/transformiix/source/xpath/nsXPathExpression.cpp index 739de44c3eb..ebfb5b59340 100644 --- a/mozilla/extensions/transformiix/source/xpath/nsXPathExpression.cpp +++ b/mozilla/extensions/transformiix/source/xpath/nsXPathExpression.cpp @@ -178,6 +178,12 @@ MBool nsXPathExpression::EvalContextImpl::isStripSpaceAllowed(Node* aNode) return MB_FALSE; } +void* nsXPathExpression::EvalContextImpl::getPrivateContext() +{ + // we don't have a private context here. + return nsnull; +} + void nsXPathExpression::EvalContextImpl::receiveError(const nsAString& aMsg, nsresult aRes) { diff --git a/mozilla/extensions/transformiix/source/xpath/txForwardContext.cpp b/mozilla/extensions/transformiix/source/xpath/txForwardContext.cpp index b16e4c5f5e1..843ac913f30 100644 --- a/mozilla/extensions/transformiix/source/xpath/txForwardContext.cpp +++ b/mozilla/extensions/transformiix/source/xpath/txForwardContext.cpp @@ -69,6 +69,12 @@ MBool txForwardContext::isStripSpaceAllowed(Node* aNode) return mInner->isStripSpaceAllowed(aNode); } +void* txForwardContext::getPrivateContext() +{ + NS_ASSERTION(mInner, "mInner is null!!!"); + return mInner->getPrivateContext(); +} + void txForwardContext::receiveError(const nsAString& aMsg, nsresult aRes) { NS_ASSERTION(mInner, "mInner is null!!!"); diff --git a/mozilla/extensions/transformiix/source/xpath/txIXPathContext.h b/mozilla/extensions/transformiix/source/xpath/txIXPathContext.h index f2cff9ffd22..06a96981415 100644 --- a/mozilla/extensions/transformiix/source/xpath/txIXPathContext.h +++ b/mozilla/extensions/transformiix/source/xpath/txIXPathContext.h @@ -115,6 +115,11 @@ public: */ virtual MBool isStripSpaceAllowed(Node* aNode) = 0; + /** + * Returns a pointer to the private context + */ + virtual void* getPrivateContext() = 0; + /* * Callback to be used by the expression/pattern if errors are detected. */ @@ -125,6 +130,7 @@ public: nsresult getVariable(PRInt32 aNamespace, nsIAtom* aLName, \ ExprResult*& aResult); \ MBool isStripSpaceAllowed(Node* aNode); \ + void* getPrivateContext(); \ void receiveError(const nsAString& aMsg, nsresult aRes) class txIEvalContext : public txIMatchContext diff --git a/mozilla/extensions/transformiix/source/xpath/txNodeSetContext.cpp b/mozilla/extensions/transformiix/source/xpath/txNodeSetContext.cpp index e28eedc4a7a..dcb6d8c9939 100644 --- a/mozilla/extensions/transformiix/source/xpath/txNodeSetContext.cpp +++ b/mozilla/extensions/transformiix/source/xpath/txNodeSetContext.cpp @@ -68,6 +68,12 @@ MBool txNodeSetContext::isStripSpaceAllowed(Node* aNode) return mInner->isStripSpaceAllowed(aNode); } +void* txNodeSetContext::getPrivateContext() +{ + NS_ASSERTION(mInner, "mInner is null!!!"); + return mInner->getPrivateContext(); +} + void txNodeSetContext::receiveError(const nsAString& aMsg, nsresult aRes) { NS_ASSERTION(mInner, "mInner is null!!!"); diff --git a/mozilla/extensions/transformiix/source/xpath/txNodeSetContext.h b/mozilla/extensions/transformiix/source/xpath/txNodeSetContext.h index e8a0c15170b..d5d065afc31 100644 --- a/mozilla/extensions/transformiix/source/xpath/txNodeSetContext.h +++ b/mozilla/extensions/transformiix/source/xpath/txNodeSetContext.h @@ -40,8 +40,7 @@ #define __TX_XPATH_SET_CONTEXT #include "txIXPathContext.h" - -class NodeSet; +#include "NodeSet.h" class txNodeSetContext : public txIEvalContext { @@ -50,7 +49,7 @@ public: : mContextSet(aContextNodeSet), mPosition(0), mInner(aContext) { } - ~txNodeSetContext() + virtual ~txNodeSetContext() { } @@ -67,10 +66,23 @@ public: TX_DECL_EVAL_CONTEXT; -private: +protected: NodeSet* mContextSet; PRUint32 mPosition; txIMatchContext* mInner; }; +class txOwningNodeSetContext : public txNodeSetContext +{ +public: + txOwningNodeSetContext(NodeSet* aContextNodeSet, txIMatchContext* aContext) + : txNodeSetContext(aContextNodeSet, aContext) + { + } + virtual ~txOwningNodeSetContext() + { + delete mContextSet; + } +}; + #endif // __TX_XPATH_SET_CONTEXT diff --git a/mozilla/extensions/transformiix/source/xpath/txSingleNodeContext.h b/mozilla/extensions/transformiix/source/xpath/txSingleNodeContext.h index 8fca6b21054..7f6ed2f67b9 100644 --- a/mozilla/extensions/transformiix/source/xpath/txSingleNodeContext.h +++ b/mozilla/extensions/transformiix/source/xpath/txSingleNodeContext.h @@ -66,6 +66,12 @@ public: return mInner->isStripSpaceAllowed(aNode); } + void* getPrivateContext() + { + NS_ASSERTION(mInner, "mInner is null!!!"); + return mInner->getPrivateContext(); + } + void receiveError(const nsAString& aMsg, nsresult aRes) { NS_ASSERTION(mInner, "mInner is null!!!"); diff --git a/mozilla/extensions/transformiix/source/xslt/Makefile.in b/mozilla/extensions/transformiix/source/xslt/Makefile.in index 34ed3189519..717533680ae 100644 --- a/mozilla/extensions/transformiix/source/xslt/Makefile.in +++ b/mozilla/extensions/transformiix/source/xslt/Makefile.in @@ -44,28 +44,40 @@ REQUIRES += dom \ webshell \ docshell \ layout \ + uconv \ + $(NULL) +else +REQUIRES += expat \ $(NULL) endif -CPPSRCS = txOutputFormat.cpp \ - ProcessorState.cpp \ +CPPSRCS = \ txBufferingHandler.cpp \ + txExecutionState.cpp \ + txInstructions.cpp \ + txOutputFormat.cpp \ txRtfHandler.cpp \ + txStylesheet.cpp \ + txStylesheetCompileHandlers.cpp \ + txStylesheetCompiler.cpp \ txTextHandler.cpp \ + txToplevelItems.cpp \ txXSLTNumber.cpp \ txXSLTNumberCounters.cpp \ txXSLTPatterns.cpp \ + txXSLTProcessor.cpp \ txPatternParser.cpp \ - txUnknownHandler.cpp \ - XSLTProcessor.cpp + txUnknownHandler.cpp ifdef TX_EXE CPPSRCS += txHTMLOutput.cpp \ txStandaloneXSLTProcessor.cpp \ + txStandaloneStylesheetCompiler.cpp \ txTextOutput.cpp \ txXMLOutput.cpp else -CPPSRCS += txMozillaTextOutput.cpp \ +CPPSRCS += txMozillaStylesheetCompiler.cpp \ + txMozillaTextOutput.cpp \ txMozillaXMLOutput.cpp \ txMozillaXSLTProcessor.cpp endif @@ -76,5 +88,8 @@ INCLUDES += -I$(srcdir) -I$(srcdir)/../base \ -I$(srcdir)/../xml -I$(srcdir)/../xml/dom \ -I$(srcdir)/../xml/parser \ -I$(srcdir)/../xpath -I$(srcdir)/util -I$(srcdir)/functions +ifdef TX_EXE +DEFINES += -DXML_DTD -DXML_UNICODE +endif libs:: $(OBJS) diff --git a/mozilla/extensions/transformiix/source/xslt/ProcessorState.cpp b/mozilla/extensions/transformiix/source/xslt/ProcessorState.cpp deleted file mode 100644 index b54d08d2096..00000000000 --- a/mozilla/extensions/transformiix/source/xslt/ProcessorState.cpp +++ /dev/null @@ -1,1279 +0,0 @@ -/* -*- 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 - * 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 The MITRE Corporation. - * Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation. - * - * Portions created by Keith Visco as a Non MITRE employee, - * (C) 1999-2000 Keith Visco. All Rights Reserved. - * - * Contributor(s): - * Keith Visco, kvisco@ziplink.net - * -- original author. - * - * Olivier Gerardin, ogerardin@vo.lu - * -- added code in ::resolveFunctionCall to support the - * document() function. - * - */ - -/** - * Implementation of ProcessorState - * Much of this code was ported from XSL:P -**/ - -#include "ProcessorState.h" -#include "XSLTFunctions.h" -#include "FunctionLib.h" -#include "txURIUtils.h" -#include "XMLUtils.h" -#include "XMLDOMUtils.h" -#include "ExprResult.h" -#include "txXMLParser.h" -#include "TxLog.h" -#include "txAtoms.h" -#include "txSingleNodeContext.h" -#include "txTokenizer.h" -#include "txVariableMap.h" -#include "XSLTProcessor.h" - - -DHASH_WRAPPER(txLoadedDocumentsBase, txLoadedDocumentEntry, nsAString&) - -nsresult txLoadedDocumentsHash::init(Document* aSourceDocument, - Document* aStyleDocument) -{ - nsresult rv = Init(8); - NS_ENSURE_SUCCESS(rv, rv); - - mSourceDocument = aSourceDocument; - mStyleDocument = aStyleDocument; - - if (mSourceDocument) { - Add(mSourceDocument); - } - if (mStyleDocument) { - Add(mStyleDocument); - } - - return NS_OK; -} - -txLoadedDocumentsHash::~txLoadedDocumentsHash() -{ - if (!mHashTable.ops) { - return; - } - - nsAutoString baseURI; - if (mSourceDocument) { - mSourceDocument->getBaseURI(baseURI); - txLoadedDocumentEntry* entry = GetEntry(baseURI); - if (entry) { - entry->mDocument = nsnull; - } - } - if (mStyleDocument) { - mStyleDocument->getBaseURI(baseURI); - txLoadedDocumentEntry* entry = GetEntry(baseURI); - if (entry) { - entry->mDocument = nsnull; - } - } -} - -void txLoadedDocumentsHash::Add(Document* aDocument) -{ - if (!mHashTable.ops) { - return; - } - - nsAutoString baseURI; - aDocument->getBaseURI(baseURI); - txLoadedDocumentEntry* entry = AddEntry(baseURI); - if (entry) { - entry->mDocument = aDocument; - } -} - -Document* txLoadedDocumentsHash::Get(const nsAString& aURI) -{ - if (!mHashTable.ops) { - return nsnull; - } - - txLoadedDocumentEntry* entry = GetEntry(aURI); - if (entry) { - return entry->mDocument; - } - - return nsnull; -} - - -/** - * Creates a new ProcessorState for the given XSL document -**/ -ProcessorState::ProcessorState(Node* aSourceNode, Document* aXslDocument) - : mOutputHandler(0), - mResultHandler(0), - mOutputHandlerFactory(0), - mXslKeys(MB_TRUE), - mKeyHash(mXslKeys), - mDecimalFormats(MB_TRUE), - mEvalContext(0), - mLocalVariables(0), - mGlobalVariableValues(MB_TRUE), - mRTFDocument(0), - mSourceNode(aSourceNode) -{ - NS_ASSERTION(aSourceNode, "missing source node"); - NS_ASSERTION(aXslDocument, "missing xslt document"); - - Document* sourceDoc; - if (mSourceNode->getNodeType() == Node::DOCUMENT_NODE) { - sourceDoc = (Document*)mSourceNode; - } - else { - sourceDoc = mSourceNode->getOwnerDocument(); - } - mLoadedDocuments.init(sourceDoc, aXslDocument); - - /* turn object deletion on for some of the Maps */ - mExprHashes[SelectAttr].setOwnership(Map::eOwnsItems); - mExprHashes[TestAttr].setOwnership(Map::eOwnsItems); - mExprHashes[ValueAttr].setOwnership(Map::eOwnsItems); - mPatternHashes[CountAttr].setOwnership(Map::eOwnsItems); - mPatternHashes[FromAttr].setOwnership(Map::eOwnsItems); - - mKeyHash.init(); -} - -/** - * Destroys this ProcessorState -**/ -ProcessorState::~ProcessorState() -{ - // Delete all ImportFrames - txListIterator iter(&mImportFrames); - while (iter.hasNext()) - delete (ImportFrame*)iter.next(); - - // in module the outputhandler is refcounted -#ifdef TX_EXE - delete mOutputHandler; -#endif -} //-- ~ProcessorState - - -/* - * Adds the given attribute set to the list of available named attribute - * sets - * @param aAttributeSet the Element to add as a named attribute set - * @param aImportFrame ImportFrame to add the attributeset to - */ -void ProcessorState::addAttributeSet(Element* aAttributeSet, - ImportFrame* aImportFrame) -{ - if (!aAttributeSet) - return; - - nsAutoString nameStr; - txExpandedName name; - aAttributeSet->getAttr(txXSLTAtoms::name, kNameSpaceID_None, nameStr); - nsresult rv = name.init(nameStr, aAttributeSet, MB_FALSE); - if (NS_FAILED(rv)) { - receiveError(NS_LITERAL_STRING("missing or malformed name for xsl:attribute-set")); - return; - } - // Get attribute set, if already exists, then merge - NodeSet* attSet = (NodeSet*)aImportFrame->mNamedAttributeSets.get(name); - if (!attSet) { - attSet = new NodeSet(); - aImportFrame->mNamedAttributeSets.add(name, attSet); - } - - // Add xsl:attribute elements to attSet - Node* node = aAttributeSet->getFirstChild(); - while (node) { - if (node->getNodeType() == Node::ELEMENT_NODE) { - PRInt32 nsID = node->getNamespaceID(); - if (nsID != kNameSpaceID_XSLT) - continue; - nsCOMPtr nodeName; - if (!node->getLocalName(getter_AddRefs(nodeName)) || !nodeName) - continue; - if (nodeName == txXSLTAtoms::attribute) - attSet->append(node); - } - node = node->getNextSibling(); - } - -} -/** - * Registers the given ErrorObserver with this ProcessorState -**/ -void ProcessorState::addErrorObserver(ErrorObserver& errorObserver) { - errorObservers.add(&errorObserver); -} //-- addErrorObserver - -/** - * Adds the given template to the list of templates to process - * @param xslTemplate The Element to add as a template - * @param importFrame ImportFrame to add the template to -**/ -void ProcessorState::addTemplate(Element* aXslTemplate, - ImportFrame* aImportFrame) -{ - NS_ASSERTION(aXslTemplate, "missing template"); - - nsresult rv = NS_OK; - nsAutoString nameStr; - if (aXslTemplate->getAttr(txXSLTAtoms::name, - kNameSpaceID_None, nameStr)) { - txExpandedName name; - rv = name.init(nameStr, aXslTemplate, MB_FALSE); - if (NS_FAILED(rv)) { - receiveError(NS_LITERAL_STRING("missing or malformed template name: '") + - nameStr + NS_LITERAL_STRING("'"), NS_ERROR_FAILURE); - return; - } - - rv = aImportFrame->mNamedTemplates.add(name, aXslTemplate); - if (NS_FAILED(rv)) { - receiveError(NS_LITERAL_STRING("Unable to add template named '") + - nameStr + - NS_LITERAL_STRING("'. Does that name already exist?"), - NS_ERROR_FAILURE); - return; - } - } - - nsAutoString match; - if (!aXslTemplate->getAttr(txXSLTAtoms::match, kNameSpaceID_None, match)) { - // This is no error, see section 6 Named Templates - return; - } - - // get the txList for the right mode - nsAutoString modeStr; - txExpandedName mode; - if (aXslTemplate->getAttr(txXSLTAtoms::mode, kNameSpaceID_None, modeStr)) { - rv = mode.init(modeStr, aXslTemplate, MB_FALSE); - if (NS_FAILED(rv)) { - receiveError(NS_LITERAL_STRING("malformed template-mode name: '") + - modeStr + NS_LITERAL_STRING("'"), NS_ERROR_FAILURE); - return; - } - } - txList* templates = - (txList*)aImportFrame->mMatchableTemplates.get(mode); - - if (!templates) { - templates = new txList; - if (!templates) { - NS_ASSERTION(0, "out of memory"); - return; - } - rv = aImportFrame->mMatchableTemplates.add(mode, templates); - if (NS_FAILED(rv)) { - delete templates; - return; - } - } - - // Check for explicit default priority - MBool hasPriority; - double priority; - nsAutoString prio; - if ((hasPriority = - aXslTemplate->getAttr(txXSLTAtoms::priority, kNameSpaceID_None, - prio))) { - priority = Double::toDouble(prio); - } - - // Get the pattern - txPSParseContext context(this, aXslTemplate); - txPattern* pattern = txPatternParser::createPattern(match, &context, this); -#ifdef TX_PATTERN_DEBUG - nsAutoString foo; - pattern->toString(foo); -#endif - - if (!pattern) { - return; - } - - // Add the simple patterns to the list of matchable templates, according - // to default priority - txList simpleMatches; - pattern->getSimplePatterns(simpleMatches); - txListIterator simples(&simpleMatches); - while (simples.hasNext()) { - txPattern* simple = (txPattern*)simples.next(); - if (simple != pattern && pattern) { - // txUnionPattern, it doesn't own the txLocPathPatterns no more, - // so delete it. (only once, of course) - delete pattern; - pattern = 0; - } - if (!hasPriority) { - priority = simple->getDefaultPriority(); - } - MatchableTemplate* nt = new MatchableTemplate(aXslTemplate, - simple, - priority); - if (!nt) { - NS_ASSERTION(0, "out of mem"); - return; - } - txListIterator templ(templates); - MBool isLast = MB_TRUE; - while (templ.hasNext() && isLast) { - MatchableTemplate* mt = (MatchableTemplate*)templ.next(); - if (priority < mt->mPriority) { - continue; - } - templ.addBefore(nt); - isLast = MB_FALSE; - } - if (isLast) - templates->add(nt); - } -} - -/* - * Adds the given LRE Stylesheet to the list of templates to process - * @param aStylesheet The Stylesheet to add as a template - * @param importFrame ImportFrame to add the template to - */ -void ProcessorState::addLREStylesheet(Document* aStylesheet, - ImportFrame* aImportFrame) -{ - NS_ASSERTION(aStylesheet, "missing stylesheet"); - - // get the txList for null mode - txExpandedName nullMode; - txList* templates = - (txList*)aImportFrame->mMatchableTemplates.get(nullMode); - - if (!templates) { - templates = new txList; - if (!templates) { - // XXX ErrorReport: out of memory - return; - } - aImportFrame->mMatchableTemplates.add(nullMode, templates); - } - - // Add the template to the list of templates - txPattern* root = new txRootPattern(MB_TRUE); - MatchableTemplate* nt = 0; - if (root) - nt = new MatchableTemplate(aStylesheet, root, 0.5); - if (!nt) { - delete root; - // XXX ErrorReport: out of memory - return; - } - txListIterator templ(templates); - MBool isLast = MB_TRUE; - while (templ.hasNext() && isLast) { - MatchableTemplate* mt = (MatchableTemplate*)templ.next(); - if (0.5 < mt->mPriority) { - continue; - } - templ.addBefore(nt); - isLast = MB_FALSE; - } - if (isLast) - templates->add(nt); -} - -/* - * 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 - * supplied, the element with seleced id is returned. - * The returned document is owned by the ProcessorState - * - * @param uri the URI of the document to retrieve - * @param baseUri the base URI used to resolve the URI if uri is relative - * @return loaded document or element pointed to by fragment identifier. If - * loading or parsing fails NULL will be returned. - */ -Node* ProcessorState::retrieveDocument(const nsAString& uri, - const nsAString& baseUri) -{ - nsAutoString absUrl; - URIUtils::resolveHref(uri, baseUri, absUrl); - - PRInt32 hash = absUrl.RFindChar(PRUnichar('#')); - PRUint32 urlEnd, fragStart, fragEnd; - if (hash == kNotFound) { - urlEnd = absUrl.Length(); - fragStart = 0; - fragEnd = 0; - } - else { - urlEnd = hash; - fragStart = hash + 1; - fragEnd = absUrl.Length(); - } - - nsDependentSubstring docUrl(absUrl, 0, urlEnd); - nsDependentSubstring frag(absUrl, fragStart, fragEnd); - - PR_LOG(txLog::xslt, PR_LOG_DEBUG, - ("Retrieve Document %s, uri %s, baseUri %s, fragment %s\n", - NS_LossyConvertUCS2toASCII(docUrl).get(), - NS_LossyConvertUCS2toASCII(uri).get(), - NS_LossyConvertUCS2toASCII(baseUri).get(), - NS_LossyConvertUCS2toASCII(frag).get())); - - // try to get already loaded document - Document* xmlDoc = mLoadedDocuments.Get(docUrl); - - if (!xmlDoc) { - // open URI - nsAutoString errMsg, refUri; - // XXX we should get the referrer from the actual node - // triggering the load, but this will do for the time being - mLoadedDocuments.mStyleDocument->getBaseURI(refUri); - nsresult rv; - rv = txParseDocumentFromURI(docUrl, refUri, - mLoadedDocuments.mStyleDocument, errMsg, - &xmlDoc); - - if (NS_FAILED(rv) || !xmlDoc) { - receiveError(NS_LITERAL_STRING("Couldn't load document '") + - docUrl + NS_LITERAL_STRING("': ") + errMsg, - NS_ERROR_XSLT_INVALID_URL); - return NULL; - } - // add to list of documents - mLoadedDocuments.Add(xmlDoc); - } - - // return element with supplied id if supplied - if (!frag.IsEmpty()) - return xmlDoc->getElementById(frag); - - return xmlDoc; -} - -/* - * Return list of import containers - */ -List* ProcessorState::getImportFrames() -{ - return &mImportFrames; -} - -/* - * Find template in specified mode matching the supplied node. Only search - * templates imported by a specific ImportFrame - * @param aNode node to find matching template for - * @param aMode mode of the template - * @param aImportedBy seach only templates imported by this ImportFrame, - * or null to search all templates - * @param aImportFrame out-param, is set to the ImportFrame containing - * the found template - * @return root-node of found template, null if none is found - */ -Node* ProcessorState::findTemplate(Node* aNode, - const txExpandedName& aMode, - ImportFrame* aImportedBy, - ImportFrame** aImportFrame) -{ - NS_ASSERTION(aImportFrame, "missing ImportFrame pointer"); - NS_ASSERTION(aNode, "missing node"); - - if (!aNode) - return 0; - - Node* matchTemplate = 0; - ImportFrame* endFrame = 0; - txListIterator frameIter(&mImportFrames); - - if (aImportedBy) { - ImportFrame* curr = (ImportFrame*)frameIter.next(); - while (curr != aImportedBy) - curr = (ImportFrame*)frameIter.next(); - - endFrame = aImportedBy->mFirstNotImported; - } - - ImportFrame* frame; - while (!matchTemplate && - (frame = (ImportFrame*)frameIter.next()) && - frame != endFrame) { - - // get templatelist for this mode - txList* templates; - templates = (txList*)frame->mMatchableTemplates.get(aMode); - - if (templates) { - txListIterator templateIter(templates); - - // Find template with highest priority - MatchableTemplate* templ; - while (!matchTemplate && - (templ = (MatchableTemplate*)templateIter.next())) { -#ifdef TX_PATTERN_DEBUG - nsAutoString foo; - templ->mMatch->toString(foo); -#endif - if (templ->mMatch->matches(aNode, this)) { - matchTemplate = templ->mTemplate; - *aImportFrame = frame; - } - } - } - } - -#ifdef PR_LOGGING - nsAutoString mode, nodeName; - if (aMode.mLocalName) { - aMode.mLocalName->ToString(mode); - } - aNode->getNodeName(nodeName); - if (matchTemplate) { - nsAutoString matchAttr; - // matchTemplate can be a document (see addLREStylesheet) - unsigned short nodeType = matchTemplate->getNodeType(); - if (nodeType == Node::ELEMENT_NODE) { - ((Element*)matchTemplate)->getAttr(txXSLTAtoms::match, - kNameSpaceID_None, - matchAttr); - } - nsAutoString baseURI; - matchTemplate->getBaseURI(baseURI); - PR_LOG(txLog::xslt, PR_LOG_DEBUG, - ("MatchTemplate, Pattern %s, Mode %s, Stylesheet %s, " \ - "Node %s\n", - NS_LossyConvertUCS2toASCII(matchAttr).get(), - NS_LossyConvertUCS2toASCII(mode).get(), - NS_LossyConvertUCS2toASCII(baseURI).get(), - NS_LossyConvertUCS2toASCII(nodeName).get())); - } - else { - PR_LOG(txLog::xslt, PR_LOG_DEBUG, - ("No match, Node %s, Mode %s\n", - NS_LossyConvertUCS2toASCII(nodeName).get(), - NS_LossyConvertUCS2toASCII(mode).get())); - } -#endif - return matchTemplate; -} - -/* - * Gets current template rule - */ -ProcessorState::TemplateRule* ProcessorState::getCurrentTemplateRule() -{ - return mCurrentTemplateRule; -} - -/* - * Sets current template rule - */ -void ProcessorState::setCurrentTemplateRule(TemplateRule* aTemplateRule) -{ - mCurrentTemplateRule = aTemplateRule; -} - -/** - * Returns the AttributeSet associated with the given name - * or null if no AttributeSet is found - */ -NodeSet* ProcessorState::getAttributeSet(const txExpandedName& aName) -{ - NodeSet* attset = new NodeSet; - if (!attset) - return attset; - - ImportFrame* frame; - txListIterator frameIter(&mImportFrames); - frameIter.resetToEnd(); - - while ((frame = (ImportFrame*)frameIter.previous())) { - NodeSet* nodes = (NodeSet*)frame->mNamedAttributeSets.get(aName); - if (nodes) - attset->append(nodes); - } - return attset; -} - -Expr* ProcessorState::getExpr(Element* aElem, ExprAttr aAttr) -{ - NS_ASSERTION(aElem, "missing element while getting expression"); - - Expr* expr = (Expr*)mExprHashes[aAttr].get(aElem); - if (expr) { - return expr; - } - nsAutoString attr; - MBool hasAttr = MB_FALSE; - switch (aAttr) { - case SelectAttr: - hasAttr = aElem->getAttr(txXSLTAtoms::select, kNameSpaceID_None, - attr); - break; - case TestAttr: - hasAttr = aElem->getAttr(txXSLTAtoms::test, kNameSpaceID_None, - attr); - break; - case ValueAttr: - hasAttr = aElem->getAttr(txXSLTAtoms::value, kNameSpaceID_None, - attr); - break; - } - - if (!hasAttr) - return 0; - - txPSParseContext pContext(this, aElem); - expr = ExprParser::createExpr(attr, &pContext); - - if (!expr) { - receiveError(NS_LITERAL_STRING("Error in parsing XPath expression: ") + - attr, NS_ERROR_XPATH_PARSE_FAILED); - } - else { - mExprHashes[aAttr].put(aElem, expr); - } - return expr; -} - -txPattern* ProcessorState::getPattern(Element* aElem, PatternAttr aAttr) -{ - NS_ASSERTION(aElem, "missing element while getting pattern"); - - txPattern* pattern = (txPattern*)mPatternHashes[aAttr].get(aElem); - if (pattern) { - return pattern; - } - nsAutoString attr; - MBool hasAttr = MB_FALSE; - switch (aAttr) { - case CountAttr: - hasAttr = aElem->getAttr(txXSLTAtoms::count, kNameSpaceID_None, - attr); - break; - case FromAttr: - hasAttr = aElem->getAttr(txXSLTAtoms::from, kNameSpaceID_None, - attr); - break; - } - - if (!hasAttr) - return 0; - - - txPSParseContext pContext(this, aElem); - pattern = txPatternParser::createPattern(attr, &pContext, this); - - if (!pattern) { - receiveError(NS_LITERAL_STRING("Error in parsing pattern: ") + attr, - NS_ERROR_XPATH_PARSE_FAILED); - } - else { - mPatternHashes[aAttr].put(aElem, pattern); - } - return pattern; -} - -/* - * Returns the template associated with the given name, or - * null if not template is found - */ -Element* ProcessorState::getNamedTemplate(const txExpandedName& aName) -{ - ImportFrame* frame; - txListIterator frameIter(&mImportFrames); - - while ((frame = (ImportFrame*)frameIter.next())) { - Element* templ = (Element*)frame->mNamedTemplates.get(aName); - if (templ) - return templ; - } - return 0; -} - -txOutputFormat* ProcessorState::getOutputFormat() -{ - return &mOutputFormat; -} - -Document* ProcessorState::getStylesheetDocument() -{ - NS_ASSERTION(mLoadedDocuments.mStyleDocument, - "missing stylesheet document"); - return mLoadedDocuments.mStyleDocument; -} - -/* - * Add a global variable - */ -nsresult ProcessorState::addGlobalVariable(const txExpandedName& aVarName, - Element* aVarElem, - ImportFrame* aImportFrame, - ExprResult* aDefaultValue) -{ - // 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 mGlobalVariableValues.add(aVarName, var); -} - -/* - * Returns map on top of the stack of local variable-bindings - */ -txVariableMap* ProcessorState::getLocalVariables() -{ - return mLocalVariables; -} - -/* - * Sets top map of the local variable-bindings stack - */ -void ProcessorState::setLocalVariables(txVariableMap* aMap) -{ - mLocalVariables = aMap; -} - -void ProcessorState::processAttrValueTemplate(const nsAFlatString& aAttValue, - Element* aContext, - nsAString& aResult) -{ - aResult.Truncate(); - txPSParseContext pContext(this, aContext); - AttributeValueTemplate* avt = - ExprParser::createAttributeValueTemplate(aAttValue, &pContext); - - if (!avt) { - // fallback, just copy the attribute - aResult.Append(aAttValue); - return; - } - - ExprResult* exprResult = avt->evaluate(this->getEvalContext()); - delete avt; - if (!exprResult) { - // XXX ErrorReport: out of memory - return; - } - - exprResult->stringValue(aResult); - delete exprResult; -} - -/** - * Adds the set of names to the Whitespace handling list. - * xsl:strip-space calls this with MB_TRUE, xsl:preserve-space - * with MB_FALSE - */ -void ProcessorState::shouldStripSpace(const nsAString& aNames, - Element* aElement, - MBool aShouldStrip, - ImportFrame* aImportFrame) -{ - //-- split names on whitespace - txTokenizer tokenizer(PromiseFlatString(aNames)); - while (tokenizer.hasMoreTokens()) { - const nsAString& name = tokenizer.nextToken(); - PRInt32 aNSID = kNameSpaceID_None; - nsCOMPtr prefix; - XMLUtils::getPrefix(name, getter_AddRefs(prefix)); - if (prefix) { - aNSID = aElement->lookupNamespaceID(prefix); - } - nsCOMPtr localName; - XMLUtils::getLocalPart(name, getter_AddRefs(localName)); - txNameTestItem* nti = new txNameTestItem(prefix, localName, - aNSID, aShouldStrip); - if (!nti) { - // XXX error report, parsing error or out of mem - break; - } - double priority = nti->getDefaultPriority(); - txListIterator iter(&aImportFrame->mWhiteNameTests); - while (iter.hasNext()) { - txNameTestItem* iNameTest = (txNameTestItem*)iter.next(); - if (iNameTest->getDefaultPriority() <= priority) { - break; - } - } - iter.addBefore(nti); - } - -} //-- stripSpace - -/** - * Adds the supplied xsl:key to the set of keys -**/ -MBool ProcessorState::addKey(Element* aKeyElem) -{ - nsresult rv = NS_OK; - nsAutoString keyQName; - aKeyElem->getAttr(txXSLTAtoms::name, kNameSpaceID_None, keyQName); - txExpandedName keyName; - rv = keyName.init(keyQName, aKeyElem, MB_FALSE); - if (NS_FAILED(rv)) - return MB_FALSE; - - txXSLKey* xslKey = (txXSLKey*)mXslKeys.get(keyName); - if (!xslKey) { - xslKey = new txXSLKey(keyName); - if (!xslKey) - return MB_FALSE; - rv = mXslKeys.add(keyName, xslKey); - if (NS_FAILED(rv)) - return MB_FALSE; - } - txPattern* match = 0; - txPSParseContext pContext(this, aKeyElem); - nsAutoString attrVal; - if (aKeyElem->getAttr(txXSLTAtoms::match, kNameSpaceID_None, attrVal)) { - match = txPatternParser::createPattern(attrVal, &pContext, this); - } - Expr* use = 0; - attrVal.Truncate(); - if (aKeyElem->getAttr(txXSLTAtoms::use, kNameSpaceID_None, attrVal)) { - use = ExprParser::createExpr(attrVal, &pContext); - } - if (!match || !use || !xslKey->addKey(match, use)) { - delete match; - delete use; - return MB_FALSE; - } - return MB_TRUE; -} - -/* - * Adds a decimal format. Returns false if the format already exists - * but dosn't contain the exact same parametervalues - */ -MBool ProcessorState::addDecimalFormat(Element* element) -{ - // build new DecimalFormat structure - nsresult rv = NS_OK; - MBool success = MB_TRUE; - txDecimalFormat* format = new txDecimalFormat; - if (!format) - return MB_FALSE; - - nsAutoString formatNameStr, attValue; - txExpandedName formatName; - if (element->getAttr(txXSLTAtoms::name, kNameSpaceID_None, - formatNameStr)) { - rv = formatName.init(formatNameStr, element, MB_FALSE); - if (NS_FAILED(rv)) - return MB_FALSE; - } - - if (element->getAttr(txXSLTAtoms::decimalSeparator, - kNameSpaceID_None, attValue)) { - if (attValue.Length() == 1) - format->mDecimalSeparator = attValue.CharAt(0); - else - success = MB_FALSE; - } - - if (element->getAttr(txXSLTAtoms::groupingSeparator, - kNameSpaceID_None, attValue)) { - if (attValue.Length() == 1) - format->mGroupingSeparator = attValue.CharAt(0); - else - success = MB_FALSE; - } - - if (element->getAttr(txXSLTAtoms::infinity, - kNameSpaceID_None, attValue)) - format->mInfinity=attValue; - - if (element->getAttr(txXSLTAtoms::minusSign, - kNameSpaceID_None, attValue)) { - if (attValue.Length() == 1) - format->mMinusSign = attValue.CharAt(0); - else - success = MB_FALSE; - } - - if (element->getAttr(txXSLTAtoms::NaN, kNameSpaceID_None, - attValue)) - format->mNaN=attValue; - - if (element->getAttr(txXSLTAtoms::percent, kNameSpaceID_None, - attValue)) { - if (attValue.Length() == 1) - format->mPercent = attValue.CharAt(0); - else - success = MB_FALSE; - } - - if (element->getAttr(txXSLTAtoms::perMille, - kNameSpaceID_None, attValue)) { - if (attValue.Length() == 1) - format->mPerMille = attValue.CharAt(0); - else if (!attValue.IsEmpty()) - success = MB_FALSE; - } - - if (element->getAttr(txXSLTAtoms::zeroDigit, - kNameSpaceID_None, attValue)) { - if (attValue.Length() == 1) - format->mZeroDigit = attValue.CharAt(0); - else if (!attValue.IsEmpty()) - success = MB_FALSE; - } - - if (element->getAttr(txXSLTAtoms::digit, kNameSpaceID_None, - attValue)) { - if (attValue.Length() == 1) - format->mDigit = attValue.CharAt(0); - else - success = MB_FALSE; - } - - if (element->getAttr(txXSLTAtoms::patternSeparator, - kNameSpaceID_None, attValue)) { - if (attValue.Length() == 1) - format->mPatternSeparator = attValue.CharAt(0); - else - success = MB_FALSE; - } - - if (!success) { - delete format; - return MB_FALSE; - } - - // Does an existing format with that name exist? - txDecimalFormat* existing = - (txDecimalFormat*)mDecimalFormats.get(formatName); - if (existing) { - success = existing->isEqual(format); - delete format; - } - else { - rv = mDecimalFormats.add(formatName, format); - if (NS_FAILED(rv)) { - delete format; - success = MB_FALSE; - } - } - - return success; -} - -/* - * Returns a decimal format or NULL if no such format exists. - */ -txDecimalFormat* ProcessorState::getDecimalFormat(const txExpandedName& aName) -{ - txDecimalFormat* format = (txDecimalFormat*)mDecimalFormats.get(aName); - if (!format && !aName.mLocalName && - aName.mNamespaceID == kNameSpaceID_None) - return &mDefaultDecimalFormat; - return format; -} - -/** - * Returns the value of a given variable binding within the current scope - * @param the name to which the desired variable value has been bound - * @return the ExprResult which has been bound to the variable with the given - * name -**/ -nsresult ProcessorState::getVariable(PRInt32 aNamespace, nsIAtom* aLName, - ExprResult*& aResult) -{ - nsresult rv; - aResult = 0; - ExprResult* exprResult; - txExpandedName varName(aNamespace, aLName); - - // Check local variables - if (mLocalVariables) { - exprResult = mLocalVariables->getVariable(varName); - if (exprResult) { - aResult = exprResult; - return NS_OK; - } - } - - // Check if global variable is already evaluated - GlobalVariableValue* globVar; - globVar = (GlobalVariableValue*)mGlobalVariableValues.get(varName); - if (globVar) { - if (globVar->mFlags == GlobalVariableValue::evaluating) { - receiveError(NS_LITERAL_STRING("Cyclic variable-value detected"), - NS_ERROR_FAILURE); - return NS_ERROR_FAILURE; - } - aResult = globVar->mValue; - return NS_OK; - } - - // We need to evaluate the variable - - // Search ImportFrames for the variable - ImportFrame* frame; - txListIterator frameIter(&mImportFrames); - Element* varElem = 0; - while (!varElem && (frame = (ImportFrame*)frameIter.next())) - varElem = (Element*)frame->mVariables.get(varName); - - if (!varElem) - return NS_ERROR_FAILURE; - - // Evaluate the variable - globVar = new GlobalVariableValue(); - if (!globVar) - return NS_ERROR_OUT_OF_MEMORY; - rv = mGlobalVariableValues.add(varName, globVar); - if (NS_FAILED(rv)) { - delete globVar; - return rv; - } - - // Set up the state we have at the beginning of the transformation - txVariableMap *oldVars = mLocalVariables; - mLocalVariables = 0; - txSingleNodeContext evalContext(mSourceNode, this); - txIEvalContext* priorEC = setEvalContext(&evalContext); - // Compute the variable value - globVar->mFlags = GlobalVariableValue::evaluating; - globVar->mValue = txXSLTProcessor::processVariable(varElem, this); - setEvalContext(priorEC); - mLocalVariables = oldVars; - - // evaluation is over, the gvv now owns the ExprResult - globVar->mFlags = GlobalVariableValue::owned; - aResult = globVar->mValue; - return NS_OK; -} - -/** - * Determines if the given XML node allows Whitespace stripping -**/ -MBool ProcessorState::isStripSpaceAllowed(Node* aNode) -{ - if (!aNode) - return MB_FALSE; - - switch (aNode->getNodeType()) { - case Node::ELEMENT_NODE: - { - // check Whitespace stipping handling list against given Node - ImportFrame* frame; - txListIterator frameIter(&mImportFrames); - - while ((frame = (ImportFrame*)frameIter.next())) { - txListIterator iter(&frame->mWhiteNameTests); - while (iter.hasNext()) { - txNameTestItem* iNameTest = (txNameTestItem*)iter.next(); - if (iNameTest->matches(aNode, this)) { - if (iNameTest->stripsSpace() && - !XMLUtils::getXMLSpacePreserve(aNode)) { - return MB_TRUE; - } - return MB_FALSE; - } - } - } - break; - } - case Node::TEXT_NODE: - case Node::CDATA_SECTION_NODE: - { - if (!XMLUtils::isWhitespace(aNode)) - return MB_FALSE; - return isStripSpaceAllowed(aNode->getParentNode()); - } - case Node::DOCUMENT_NODE: - { - return MB_TRUE; - } - } - return MB_FALSE; -} - -/** - * Notifies this Error observer of a new error using the given error level -**/ -void ProcessorState::receiveError(const nsAString& errorMessage, nsresult aRes) -{ - txListIterator iter(&errorObservers); - while (iter.hasNext()) { - ErrorObserver* observer = (ErrorObserver*)iter.next(); - observer->receiveError(errorMessage, aRes); - } -} - -/** - * Returns a call to the function that has the given name. - * This method is used for XPath Extension Functions. - * @return the FunctionCall for the function with the given name. -**/ -#define CHECK_FN(_name) aName == txXSLTAtoms::_name - -nsresult ProcessorState::resolveFunctionCall(nsIAtom* aName, PRInt32 aID, - Element* aElem, - FunctionCall*& aFunction) -{ - aFunction = 0; - - if (aID != kNameSpaceID_None) { - return NS_ERROR_XPATH_PARSE_FAILED; - } - if (CHECK_FN(document)) { - aFunction = new DocumentFunctionCall(this, aElem); - NS_ENSURE_TRUE(aFunction, NS_ERROR_OUT_OF_MEMORY); - return NS_OK; - } - if (CHECK_FN(key)) { - aFunction = new txKeyFunctionCall(this, aElem); - NS_ENSURE_TRUE(aFunction, NS_ERROR_OUT_OF_MEMORY); - return NS_OK; - } - if (CHECK_FN(formatNumber)) { - aFunction = new txFormatNumberFunctionCall(this, aElem); - NS_ENSURE_TRUE(aFunction, NS_ERROR_OUT_OF_MEMORY); - return NS_OK; - } - if (CHECK_FN(current)) { - aFunction = new CurrentFunctionCall(this); - NS_ENSURE_TRUE(aFunction, NS_ERROR_OUT_OF_MEMORY); - return NS_OK; - } - if (CHECK_FN(unparsedEntityUri)) { - return NS_ERROR_NOT_IMPLEMENTED; - } - if (CHECK_FN(generateId)) { - aFunction = new GenerateIdFunctionCall(); - NS_ENSURE_TRUE(aFunction, NS_ERROR_OUT_OF_MEMORY); - return NS_OK; - } - if (CHECK_FN(systemProperty)) { - aFunction = new SystemPropertyFunctionCall(aElem); - NS_ENSURE_TRUE(aFunction, NS_ERROR_OUT_OF_MEMORY); - return NS_OK; - } - if (CHECK_FN(elementAvailable)) { - aFunction = new ElementAvailableFunctionCall(aElem); - NS_ENSURE_TRUE(aFunction, NS_ERROR_OUT_OF_MEMORY); - return NS_OK; - } - if (CHECK_FN(functionAvailable)) { - aFunction = new FunctionAvailableFunctionCall(aElem); - NS_ENSURE_TRUE(aFunction, NS_ERROR_OUT_OF_MEMORY); - return NS_OK; - } - - return NS_ERROR_XPATH_PARSE_FAILED; -} //-- resolveFunctionCall - - //-------------------/ - //- Private Methods -/ -//-------------------/ - -ProcessorState::ImportFrame::ImportFrame(ImportFrame* aFirstNotImported) - : mNamedTemplates(MB_FALSE), - mMatchableTemplates(MB_TRUE), - mNamedAttributeSets(MB_TRUE), - mFirstNotImported(aFirstNotImported), - mVariables(MB_FALSE) -{ -} - -ProcessorState::ImportFrame::~ImportFrame() -{ - // Delete all txNameTestItems - txListIterator whiteIter(&mWhiteNameTests); - while (whiteIter.hasNext()) - delete (txNameTestItem*)whiteIter.next(); - - // Delete templates in mMatchableTemplates - txExpandedNameMap::iterator iter(mMatchableTemplates); - while (iter.next()) { - txListIterator templIter((txList*)iter.value()); - MatchableTemplate* templ; - while ((templ = (MatchableTemplate*)templIter.next())) { - delete templ->mMatch; - delete templ; - } - } -} - -/* - * txPSParseContext - * txIParseContext used by ProcessorState internally - */ - -nsresult txPSParseContext::resolveNamespacePrefix(nsIAtom* aPrefix, - PRInt32& aID) -{ -#ifdef DEBUG - if (!aPrefix || aPrefix == txXMLAtoms::_empty) { - // default namespace is not forwarded to xpath - NS_ASSERTION(0, "caller should handle default namespace ''"); - aID = kNameSpaceID_None; - return NS_OK; - } -#endif - aID = mStyle->lookupNamespaceID(aPrefix); - return (aID != kNameSpaceID_Unknown) ? NS_OK : NS_ERROR_FAILURE; -} - -nsresult txPSParseContext::resolveFunctionCall(nsIAtom* aName, PRInt32 aID, - FunctionCall*& aFunction) -{ - return mPS->resolveFunctionCall(aName, aID, mStyle, aFunction); -} - -PRBool txPSParseContext::caseInsensitiveNameTests() -{ - return PR_FALSE; -} - -void txPSParseContext::receiveError(const nsAString& aMsg, nsresult aRes) -{ - mPS->receiveError(aMsg, aRes); -} - -/* - * GlobalVariableValue, Used avoid circular dependencies of variables - */ - -ProcessorState::GlobalVariableValue::~GlobalVariableValue() -{ - 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 deleted file mode 100644 index 4ebdecf4f50..00000000000 --- a/mozilla/extensions/transformiix/source/xslt/ProcessorState.h +++ /dev/null @@ -1,574 +0,0 @@ -/* -*- 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 - * 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 The MITRE Corporation. - * Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation. - * - * Portions created by Keith Visco as a Non MITRE employee, - * (C) 1999 Keith Visco. All Rights Reserved. - * - * Contributor(s): - * Keith Visco, kvisco@ziplink.net - * -- original author. - * - */ - - - -#ifndef TRANSFRMX_PROCESSORSTATE_H -#define TRANSFRMX_PROCESSORSTATE_H - -#include "NodeSet.h" -#include "ErrorObserver.h" -#include "txPatternParser.h" -#include "Expr.h" -#include "txOutputFormat.h" -#include "Map.h" -#include "txIXPathContext.h" -#include "txExpandedNameMap.h" -#include "txXMLEventHandler.h" -#include "XSLTFunctions.h" -#include "txError.h" -#include "nsVoidArray.h" -#include "nsDoubleHashtable.h" -#include "txKey.h" - -class txVariableMap; -class txXSLKey; - -class txLoadedDocumentEntry : public PLDHashStringEntry { -public: - txLoadedDocumentEntry(const void* aKey) : PLDHashStringEntry(aKey) - { - } - ~txLoadedDocumentEntry() - { - delete mDocument; - } - Document* mDocument; -}; - -DECL_DHASH_WRAPPER(txLoadedDocumentsBase, txLoadedDocumentEntry, nsAString&) - -class txLoadedDocumentsHash : public txLoadedDocumentsBase -{ -public: - ~txLoadedDocumentsHash(); - nsresult init(Document* aSourceDocument, Document* aStyleDocument); - void Add(Document* aDocument); - Document* Get(const nsAString& aURI); - -private: - friend class ProcessorState; - Document* mSourceDocument; - Document* mStyleDocument; -}; - -/** - * Class used for keeping the current state of the XSL Processor - */ -class ProcessorState : public txIMatchContext { - -public: - /** - * Creates a new ProcessorState for the given XSL document - * And result Document - */ - ProcessorState(Node* aSourceNode, Document* aXslDocument); - - /** - * Destroys this ProcessorState - */ - ~ProcessorState(); - - /** - * Contain information that is import precedence dependant. - */ - class ImportFrame { - public: - ImportFrame(ImportFrame* aFirstNotImported); - ~ImportFrame(); - - // Map of named templates - txExpandedNameMap mNamedTemplates; - - // Map of template modes, each item in the map is a list - // of templates - txExpandedNameMap mMatchableTemplates; - - // List of whitespace preserving and stripping nametests - txList mWhiteNameTests; - - // Map of named attribute sets - txExpandedNameMap mNamedAttributeSets; - - // Output format, as specified by the xsl:output elements - txOutputFormat mOutputFormat; - - // ImportFrame which is the first one *not* imported by this frame - ImportFrame* mFirstNotImported; - - // Map of top-level variables/parameters - txExpandedNameMap mVariables; - - // The following stuff is missing here: - - // Namespace aliases (xsl:namespace-alias) - }; - // To be able to do some cleaning up in destructor - friend class ImportFrame; - - /** - * Adds the given attribute set to the list of available named attribute - * sets - * @param aAttributeSet the Element to add as a named attribute set - * @param aImportFrame ImportFrame to add the attributeset to - */ - void addAttributeSet(Element* aAttributeSet, ImportFrame* aImportFrame); - - /** - * Registers the given ErrorObserver with this ProcessorState - */ - void addErrorObserver(ErrorObserver& errorObserver); - - /** - * Adds the given template to the list of templates to process - * @param aXslTemplate The Element to add as a template - * @param aImportFrame ImportFrame to add the template to - */ - void addTemplate(Element* aXslTemplate, ImportFrame* aImportFrame); - - /** - * Adds the given LRE Stylesheet to the list of templates to process - * @param aStylesheet The Stylesheet to add as a template - * @param importFrame ImportFrame to add the template to - */ - void addLREStylesheet(Document* aStylesheet, ImportFrame* aImportFrame); - - /** - * Returns the AttributeSet associated with the given name - * or null if no AttributeSet is found - */ - NodeSet* getAttributeSet(const txExpandedName& aName); - - /** - * Returns the template associated with the given name, or - * null if not template is found - */ - Element* getNamedTemplate(const txExpandedName& aName); - - /** - * Returns the OutputFormat which contains information on how - * to serialize the output. - */ - txOutputFormat* getOutputFormat(); - - /** - * Add a global variable - */ - nsresult addGlobalVariable(const txExpandedName& aVarName, - Element* aVarElem, - ImportFrame* aImportFrame, - ExprResult* aDefaultValue); - - /** - * Returns map on top of the stack of local variable-bindings - */ - txVariableMap* getLocalVariables(); - - /** - * Sets top map of the local variable-bindings stack - */ - void setLocalVariables(txVariableMap* aMap); - - /** - * Enums for the getExpr and getPattern functions - */ - enum ExprAttr { - SelectAttr = 0, - TestAttr, - ValueAttr - }; - - enum PatternAttr { - CountAttr = 0, - FromAttr - }; - - Expr* getExpr(Element* aElem, ExprAttr aAttr); - txPattern* getPattern(Element* aElem, PatternAttr aAttr); - - /** - * 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 - * supplied, the element with seleced id is returned. - * The returned document is owned by the ProcessorState - * - * @param uri the URI of the document to retrieve - * @param baseUri the base URI used to resolve the URI if uri is relative - * @return loaded document or element pointed to by fragment identifier. If - * loading or parsing fails NULL will be returned. - */ - Node* retrieveDocument(const nsAString& uri, const nsAString& baseUri); - - /** - * Return stack of urls of currently entered stylesheets - */ - nsStringArray& getEnteredStylesheets() - { - return mEnteredStylesheets; - } - - /** - * Return list of import containers - */ - List* getImportFrames(); - - /** - * Find template in specified mode matching the supplied node - * @param aNode node to find matching template for - * @param aMode mode of the template - * @param aImportFrame out-param, is set to the ImportFrame containing - * the found template - * @return root-node of found template, null if none is found - */ - Node* findTemplate(Node* aNode, - const txExpandedName& aMode, - ImportFrame** aImportFrame) - { - return findTemplate(aNode, aMode, 0, aImportFrame); - } - - /** - * Find template in specified mode matching the supplied node. Only search - * templates imported by a specific ImportFrame - * @param aNode node to find matching template for - * @param aMode mode of the template - * @param aImportedBy seach only templates imported by this ImportFrame, - * or null to search all templates - * @param aImportFrame out-param, is set to the ImportFrame containing - * the found template - * @return root-node of found template, null if none is found - */ - Node* findTemplate(Node* aNode, - const txExpandedName& aMode, - ImportFrame* aImportedBy, - ImportFrame** aImportFrame); - - /** - * Struct holding information about a current template rule - */ - struct TemplateRule { - ImportFrame* mFrame; - const txExpandedName* mMode; - txVariableMap* mParams; - }; - - /** - * Gets current template rule - */ - TemplateRule* getCurrentTemplateRule(); - - /** - * Sets current template rule - */ - void setCurrentTemplateRule(TemplateRule* aTemplateRule); - - /** - * Adds the set of names to the Whitespace preserving element set - */ - void preserveSpace(nsAString& names); - - void processAttrValueTemplate(const nsAFlatString& aAttValue, - Element* aContext, - nsAString& aResult); - - /** - * Adds the set of names to the Whitespace stripping handling list. - * xsl:strip-space calls this with MB_TRUE, xsl:preserve-space - * with MB_FALSE - * aElement is used to resolve QNames - */ - void shouldStripSpace(const nsAString& aNames, Element* aElement, - MBool aShouldStrip, - ImportFrame* aImportFrame); - - /** - * Adds the supplied xsl:key to the set of keys - */ - MBool addKey(Element* aKeyElem); - - /** - * Get the nodeset for a key+document+value. Note that the result can - * only be used until the next call to this function. - * @param aKeyName Name of key. - * @param aDocument Context-document to get key-nodes in. - * @param aKeyValue Key-value to get the nodes for. - * @param aIndexIfNotFound Check if the requested key is index in the - * requested document and if it isn't index it. - * This should only be false if it's known that - * the key is already indexed in that document. - * @param aResult Out-param returning the result. This pointer - * can only be used until the next call to - * getKeyNodes. - */ - nsresult getKeyNodes(const txExpandedName& aKeyName, Document* aDocument, - const nsAString& aKeyValue, PRBool aIndexIfNotFound, - const NodeSet** aResult) - { - return mKeyHash.getKeyNodes(aKeyName, aDocument, aKeyValue, - aIndexIfNotFound, this, aResult); - } - - - /** - * Adds a decimal format. Returns false if the format already exists - * but dosn't contain the exact same parametervalues - */ - MBool addDecimalFormat(Element* element); - - /** - * Returns a decimal format or NULL if no such format exists. - */ - txDecimalFormat* getDecimalFormat(const txExpandedName& name); - - /** - * Returns the stylesheet document - */ - Document* getStylesheetDocument(); - - /** - * Virtual methods from txIEvalContext - */ - - TX_DECL_MATCH_CONTEXT; - - /** - * Set the current txIEvalContext and get the prior one - */ - txIEvalContext* setEvalContext(txIEvalContext* aEContext) - { - txIEvalContext* tmp = mEvalContext; - mEvalContext = aEContext; - return tmp; - } - - /** - * Get the current txIEvalContext - */ - txIEvalContext* getEvalContext() - { - return mEvalContext; - } - - - /** - * More other functions - */ - void receiveError(const nsAString& errorMessage) - { - receiveError(errorMessage, NS_ERROR_FAILURE); - } - - /** - * Returns a FunctionCall which has the given name. - * @return the FunctionCall for the function with the given name. - */ - nsresult resolveFunctionCall(nsIAtom* aName, PRInt32 aID, - Element* aElem, FunctionCall*& aFunction); - - txAXMLEventHandler* mOutputHandler; - txAXMLEventHandler* mResultHandler; - - txAOutputHandlerFactory* mOutputHandlerFactory; - -private: - - class MatchableTemplate { - public: - MatchableTemplate(Node* aTemplate, txPattern* aPattern, - double aPriority) - : mTemplate(aTemplate), mMatch(aPattern), mPriority(aPriority) - { - } - Node* mTemplate; - txPattern* mMatch; - double mPriority; - }; - - class GlobalVariableValue : public TxObject { - public: - GlobalVariableValue(ExprResult* aValue = 0) - : mValue(aValue), mFlags(nonOwned) - { - } - virtual ~GlobalVariableValue(); - - ExprResult* mValue; - char mFlags; - enum _flags - { - nonOwned = 0, - evaluating, - owned - }; - }; - - /** - * The list of ErrorObservers registered with this ProcessorState - */ - List errorObservers; - - /** - * Stack of URIs for currently entered stylesheets - */ - nsStringArray mEnteredStylesheets; - - /** - * List of import containers. Sorted by ascending import precedence - */ - txList mImportFrames; - - /** - * The output format used when serializing the result - */ - txOutputFormat mOutputFormat; - - /** - * The set of loaded documents. This includes both document() loaded - * documents and xsl:include/xsl:import'ed documents. - */ - txLoadedDocumentsHash mLoadedDocuments; - - /** - * The set of all available keys - */ - txExpandedNameMap mXslKeys; - - /** - * Hash of all key-values - */ - txKeyHash mKeyHash; - - /** - * The set of all avalible decimalformats - */ - txExpandedNameMap mDecimalFormats; - - /** - * Default decimal-format - */ - txDecimalFormat mDefaultDecimalFormat; - - /** - * List of hashes with parsed expression. Every listitem holds the - * expressions for an attribute name - */ - Map mExprHashes[3]; - - /** - * List of hashes with parsed patterns. Every listitem holds the - * patterns for an attribute name - */ - Map mPatternHashes[2]; - - /** - * Current txIEvalContext* - */ - txIEvalContext* mEvalContext; - - /** - * Current template rule - */ - TemplateRule* mCurrentTemplateRule; - - /** - * Top of stack of local variable-bindings - */ - txVariableMap* mLocalVariables; - - /** - * Map of values of global variables - */ - txExpandedNameMap mGlobalVariableValues; - - /** - * Document used to create RTFs - */ - Document* mRTFDocument; - - /** - * Source-node where processing started - */ - Node* mSourceNode; -}; - -/** - * txNameTestItem holds both an ElementExpr and a bool for use in - * whitespace stripping. - */ -class txNameTestItem { -public: - txNameTestItem(nsIAtom* aPrefix, nsIAtom* aLocalName, PRInt32 aNSID, - MBool stripSpace) - : mNameTest(aPrefix, aLocalName, aNSID, Node::ELEMENT_NODE), - mStrips(stripSpace) - { - } - - MBool matches(Node* aNode, txIMatchContext* aContext) { - return mNameTest.matches(aNode, aContext); - } - - MBool stripsSpace() { - return mStrips; - } - - double getDefaultPriority() { - return mNameTest.getDefaultPriority(); - } - -protected: - txNameTest mNameTest; - MBool mStrips; -}; - -/** - * txPSParseContext - * a txIParseContext forwarding all but resolveNamespacePrefix - * to a ProcessorState - */ -class txPSParseContext : public txIParseContext { -public: - txPSParseContext(ProcessorState* aPS, Element* aStyleNode) - : mPS(aPS), mStyle(aStyleNode) - { - } - - ~txPSParseContext() - { - } - - nsresult resolveNamespacePrefix(nsIAtom* aPrefix, PRInt32& aID); - nsresult resolveFunctionCall(nsIAtom* aName, PRInt32 aID, - FunctionCall*& aFunction); - PRBool caseInsensitiveNameTests(); - void receiveError(const nsAString& aMsg, nsresult aRes); - -protected: - ProcessorState* mPS; - Element* mStyle; -}; - -#endif - diff --git a/mozilla/extensions/transformiix/source/xslt/XSLTProcessor.cpp b/mozilla/extensions/transformiix/source/xslt/XSLTProcessor.cpp deleted file mode 100644 index 195187723a4..00000000000 --- a/mozilla/extensions/transformiix/source/xslt/XSLTProcessor.cpp +++ /dev/null @@ -1,1638 +0,0 @@ -/* -*- 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 - * 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 The MITRE Corporation. - * Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation. - * - * Portions created by Keith Visco as a Non MITRE employee, - * (C) 1999, 2000 Keith Visco. All Rights Reserved. - * - * Contributor(s): - * Keith Visco, kvisco@ziplink.net - * -- original author. - * - * Bob Miller, kbob@oblix.com - * -- plugged core leak. - * - * Pierre Phaneuf, pp@ludusdesign.com - * -- fixed some XPCOM usage. - * - * Marina Mechtcheriakova, mmarina@mindspring.com - * -- Added call to recurisvely attribute-set processing on - * xsl:attribute-set itself - * -- Added call to handle attribute-set processing for xsl:copy - * - * Nathan Pride, npride@wavo.com - * -- fixed a document base issue - * - * Olivier Gerardin - * -- Changed behavior of passing parameters to templates - * - */ - -#include "XSLTProcessor.h" -#include "txAtoms.h" -#include "TxLog.h" -#include "txNodeSetContext.h" -#include "txNodeSorter.h" -#include "txRtfHandler.h" -#include "txStack.h" -#include "txStringUtils.h" -#include "txTextHandler.h" -#include "txTokenizer.h" -#include "txURIUtils.h" -#include "txVariableMap.h" -#include "txXSLTNumber.h" -#include "XMLDOMUtils.h" -#include "XMLUtils.h" - -#ifdef TX_EXE -#include "txHTMLOutput.h" -#else -#include "nsContentCID.h" -#include "nsIConsoleService.h" -#include "nsIDOMDocument.h" -#include "nsIServiceManagerUtils.h" - -static NS_DEFINE_CID(kXMLDocumentCID, NS_XMLDOCUMENT_CID); -#endif - -Expr* txXSLTProcessor::gNodeExpr = 0; - -/* - * Implement static variables for atomservice and dom. - */ -#ifdef TX_EXE -TX_IMPL_DOM_STATICS; -#endif - -TX_LG_IMPL; - -/* static */ -MBool -txXSLTProcessor::txInit() -{ - TX_LG_CREATE; - - // 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()) - return MB_FALSE; - if (!txXPathAtoms::init()) - return MB_FALSE; - if (!txXSLTAtoms::init()) - return MB_FALSE; - -#ifdef TX_EXE - if (!txNamespaceManager::init()) - return MB_FALSE; - - if (NS_FAILED(txHTMLOutput::init())) { - return MB_FALSE; - } -#endif - - return MB_TRUE; -} - -/* static */ -MBool -txXSLTProcessor::txShutdown() -{ - TX_LG_DELETE; -#ifdef TX_EXE - txNamespaceManager::shutdown(); - txHTMLOutput::shutdown(); -#endif - - delete gNodeExpr; - - txHTMLAtoms::shutdown(); - txXMLAtoms::shutdown(); - txXPathAtoms::shutdown(); - txXSLTAtoms::shutdown(); - return MB_TRUE; -} - -void -txXSLTProcessor::copyNode(Node* aSourceNode, ProcessorState* aPs) -{ - if (!aSourceNode) - return; - - switch (aSourceNode->getNodeType()) { - case Node::ATTRIBUTE_NODE: - { - nsAutoString nodeName, nodeValue; - aSourceNode->getNodeName(nodeName); - aSourceNode->getNodeValue(nodeValue); - NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); - aPs->mResultHandler->attribute(nodeName, - aSourceNode->getNamespaceID(), - nodeValue); - break; - } - case Node::COMMENT_NODE: - { - nsAutoString nodeValue; - aSourceNode->getNodeValue(nodeValue); - NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); - aPs->mResultHandler->comment(nodeValue); - break; - } - case Node::DOCUMENT_NODE: - case Node::DOCUMENT_FRAGMENT_NODE: - { - // Copy children - Node* child = aSourceNode->getFirstChild(); - while (child) { - copyNode(child, aPs); - child = child->getNextSibling(); - } - break; - } - case Node::ELEMENT_NODE: - { - Element* element = (Element*)aSourceNode; - nsAutoString name; - element->getNodeName(name); - PRInt32 nsID = element->getNamespaceID(); - NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); - aPs->mResultHandler->startElement(name, nsID); - - // Copy attributes - NamedNodeMap* attList = element->getAttributes(); - if (attList) { - PRUint32 i = 0; - for (i = 0; i < attList->getLength(); i++) { - Attr* attr = (Attr*)attList->item(i); - nsAutoString nodeName, nodeValue; - attr->getNodeName(nodeName); - attr->getNodeValue(nodeValue); - NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); - aPs->mResultHandler->attribute(nodeName, - attr->getNamespaceID(), - nodeValue); - } - } - - // Copy children - Node* child = element->getFirstChild(); - while (child) { - copyNode(child, aPs); - child = child->getNextSibling(); - } - - NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); - aPs->mResultHandler->endElement(name, nsID); - break; - } - case Node::PROCESSING_INSTRUCTION_NODE: - { - ProcessingInstruction* pi = (ProcessingInstruction*)aSourceNode; - nsAutoString target, data; - pi->getNodeName(target); - pi->getNodeValue(data); - NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); - aPs->mResultHandler->processingInstruction(target, data); - break; - } - case Node::TEXT_NODE: - case Node::CDATA_SECTION_NODE: - { - nsAutoString nodeValue; - aSourceNode->getNodeValue(nodeValue); - NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); - aPs->mResultHandler->characters(nodeValue, PR_FALSE); - break; - } - } -} - -void -txXSLTProcessor::logMessage(const nsAString& aMessage) -{ -#ifdef TX_EXE - cout << "xsl:message - "<< NS_LossyConvertUCS2toASCII(aMessage).get() << 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); - 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; - - unsigned short nodeType = aAction->getNodeType(); - - // Handle text nodes - if (nodeType == Node::TEXT_NODE || - nodeType == Node::CDATA_SECTION_NODE) { - nsAutoString nodeValue; - aAction->getNodeValue(nodeValue); - if (!XMLUtils::isWhitespace(nodeValue) || - XMLUtils::getXMLSpacePreserve(aAction)) { - NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); - aPs->mResultHandler->characters(nodeValue, PR_FALSE); - } - return; - } - - if (nodeType != Node::ELEMENT_NODE) { - return; - } - - // Handle element nodes - Element* actionElement = (Element*)aAction; - PRInt32 nsID = aAction->getNamespaceID(); - if (nsID != kNameSpaceID_XSLT) { - // Literal result element - // XXX TODO Check for excluded namespaces and aliased namespaces (element and attributes) - nsAutoString nodeName; - aAction->getNodeName(nodeName); - NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); - aPs->mResultHandler->startElement(nodeName, nsID); - - processAttributeSets(actionElement, aPs); - - // Handle attributes - NamedNodeMap* atts = actionElement->getAttributes(); - - if (atts) { - // Process all non XSLT attributes - PRUint32 i; - for (i = 0; i < atts->getLength(); ++i) { - Attr* attr = (Attr*)atts->item(i); - if (attr->getNamespaceID() == kNameSpaceID_XSLT) - continue; - // Process Attribute Value Templates - nsAutoString nodeName, nodeValue, value; - attr->getNodeName(nodeName); - attr->getNodeValue(nodeValue); - aPs->processAttrValueTemplate(nodeValue, actionElement, value); - NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); - aPs->mResultHandler->attribute(nodeName, - attr->getNamespaceID(), value); - } - } - - // Process children - processChildren(actionElement, aPs); - NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); - aPs->mResultHandler->endElement(nodeName, nsID); - return; - } - - Expr* expr = 0; - nsCOMPtr localName; - aAction->getLocalName(getter_AddRefs(localName)); - // xsl:apply-imports - if (localName == txXSLTAtoms::applyImports) { - ProcessorState::TemplateRule* curr; - Node* xslTemplate; - ProcessorState::ImportFrame *frame; - - curr = aPs->getCurrentTemplateRule(); - if (!curr) { - aPs->receiveError(NS_LITERAL_STRING("apply-imports not allowed here"), - NS_ERROR_FAILURE); - return; - } - - xslTemplate = aPs->findTemplate(aPs->getEvalContext()->getContextNode(), - *curr->mMode, curr->mFrame, &frame); - processMatchedTemplate(xslTemplate, curr->mParams, *curr->mMode, - frame, aPs); - - } - // xsl:apply-templates - else if (localName == txXSLTAtoms::applyTemplates) { - if (actionElement->hasAttr(txXSLTAtoms::select, - kNameSpaceID_None)) - expr = aPs->getExpr(actionElement, - ProcessorState::SelectAttr); - else - expr = gNodeExpr; - - if (!expr) { - return; - } - - ExprResult* exprResult = expr->evaluate(aPs->getEvalContext()); - if (!exprResult) { - return; - } - - if (exprResult->getResultType() == ExprResult::NODESET) { - NodeSet* nodeSet = (NodeSet*)exprResult; - if (nodeSet->isEmpty()) { - delete nodeSet; - return; - } - - // Look for xsl:sort elements - txNodeSorter sorter(aPs); - Node* child = actionElement->getFirstChild(); - while (child) { - if (child->getNodeType() == Node::ELEMENT_NODE && - child->getNamespaceID() == kNameSpaceID_XSLT) { - nsCOMPtr childLocalName; - child->getLocalName(getter_AddRefs(childLocalName)); - if (childLocalName == txXSLTAtoms::sort) { - sorter.addSortElement((Element*)child); - } - } - child = child->getNextSibling(); - } - sorter.sortNodeSet(nodeSet); - - // Process xsl:with-param elements - txVariableMap params(0); - processParameters(actionElement, ¶ms, aPs); - - // Get mode - nsAutoString modeStr; - txExpandedName mode; - if (actionElement->getAttr(txXSLTAtoms::mode, - kNameSpaceID_None, modeStr)) { - rv = mode.init(modeStr, actionElement, MB_FALSE); - if (NS_FAILED(rv)) { - aPs->receiveError(NS_LITERAL_STRING("malformed mode-name in xsl:apply-templates")); - return; - } - } - - txNodeSetContext evalContext(nodeSet, aPs); - txIEvalContext* priorEC = - aPs->setEvalContext(&evalContext); - while (evalContext.hasNext()) { - evalContext.next(); - ProcessorState::ImportFrame *frame; - Node* currNode = evalContext.getContextNode(); - Node* xslTemplate; - xslTemplate = aPs->findTemplate(currNode, mode, &frame); - processMatchedTemplate(xslTemplate, ¶ms, mode, frame, aPs); - } - - aPs->setEvalContext(priorEC); - } - else { - aPs->receiveError(NS_LITERAL_STRING("error processing apply-templates"), - NS_ERROR_FAILURE); - } - //-- clean up - delete exprResult; - } - // xsl:attribute - else if (localName == txXSLTAtoms::attribute) { - nsAutoString nameAttr; - if (!actionElement->getAttr(txXSLTAtoms::name, - kNameSpaceID_None, nameAttr)) { - aPs->receiveError(NS_LITERAL_STRING("missing required name attribute for xsl:attribute"), NS_ERROR_FAILURE); - return; - } - - // Process name as an AttributeValueTemplate - nsAutoString name; - aPs->processAttrValueTemplate(nameAttr, actionElement, name); - - // Check name validity (must be valid QName and not xmlns) - if (!XMLUtils::isValidQName(name)) { - aPs->receiveError(NS_LITERAL_STRING("error processing xsl:attribute, ") + - name + NS_LITERAL_STRING(" is not a valid QName."), - NS_ERROR_FAILURE); - return; - } - - if (TX_StringEqualsAtom(name, txXMLAtoms::xmlns)) { - aPs->receiveError(NS_LITERAL_STRING("error processing xsl:attribute, name is xmlns."), NS_ERROR_FAILURE); - return; - } - - // Determine namespace URI from the namespace attribute or - // from the prefix of the name (using the xslt action element). - nsAutoString resultNs; - PRInt32 resultNsID = kNameSpaceID_None; - if (actionElement->getAttr(txXSLTAtoms::_namespace, kNameSpaceID_None, - resultNs)) { - nsAutoString nsURI; - aPs->processAttrValueTemplate(resultNs, actionElement, - nsURI); - resultNsID = aPs->getStylesheetDocument()->namespaceURIToID(nsURI); - } - else { - nsCOMPtr prefix; - XMLUtils::getPrefix(name, getter_AddRefs(prefix)); - if (prefix) { - if (prefix != txXMLAtoms::xmlns) - resultNsID = actionElement->lookupNamespaceID(prefix); - else - // Cut xmlns: (6 characters) - name.Cut(0, 6); - } - } - - // XXX Should verify that this is correct behaviour. Signal error too? - if (resultNsID == kNameSpaceID_Unknown) { - return; - } - - // Compute value - nsAutoString value; - processChildrenAsValue(actionElement, aPs, MB_TRUE, value); - - NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); - aPs->mResultHandler->attribute(name, resultNsID, value); - } - // xsl:call-template - else if (localName == txXSLTAtoms::callTemplate) { - nsAutoString nameStr; - txExpandedName templateName; - actionElement->getAttr(txXSLTAtoms::name, - kNameSpaceID_None, nameStr); - - rv = templateName.init(nameStr, actionElement, MB_FALSE); - if (NS_SUCCEEDED(rv)) { - Element* xslTemplate = aPs->getNamedTemplate(templateName); - if (xslTemplate) { -#ifdef PR_LOGGING - nsAutoString baseURI; - xslTemplate->getBaseURI(baseURI); - PR_LOG(txLog::xslt, PR_LOG_DEBUG, - ("CallTemplate, Name %s, Stylesheet %s\n", - NS_LossyConvertUCS2toASCII(nameStr).get(), - NS_LossyConvertUCS2toASCII(baseURI).get())); -#endif - txVariableMap params(0); - processParameters(actionElement, ¶ms, aPs); - processTemplate(xslTemplate, ¶ms, aPs); - } - } - else { - aPs->receiveError(NS_LITERAL_STRING("missing or malformed name in xsl:call-template"), NS_ERROR_FAILURE); - } - } - // xsl:choose - else if (localName == txXSLTAtoms::choose) { - Node* condition = actionElement->getFirstChild(); - MBool caseFound = MB_FALSE; - while (!caseFound && condition) { - if (condition->getNodeType() != Node::ELEMENT_NODE || - condition->getNamespaceID() != kNameSpaceID_XSLT) { - condition = condition->getNextSibling(); - continue; - } - - Element* xslTemplate = (Element*)condition; - nsCOMPtr conditionLocalName; - condition->getLocalName(getter_AddRefs(conditionLocalName)); - if (conditionLocalName == txXSLTAtoms::when) { - expr = aPs->getExpr(xslTemplate, - ProcessorState::TestAttr); - if (!expr) { - condition = condition->getNextSibling(); - continue; - } - - ExprResult* result = - expr->evaluate(aPs->getEvalContext()); - if (result && result->booleanValue()) { - processChildren(xslTemplate, aPs); - caseFound = MB_TRUE; - } - delete result; - } - else if (conditionLocalName == txXSLTAtoms::otherwise) { - processChildren(xslTemplate, aPs); - caseFound = MB_TRUE; - } - condition = condition->getNextSibling(); - } // end for-each child of xsl:choose - } - // xsl:comment - else if (localName == txXSLTAtoms::comment) { - nsAutoString value; - processChildrenAsValue(actionElement, aPs, MB_TRUE, value); - PRInt32 pos = 0; - PRUint32 length = value.Length(); - while ((pos = value.FindChar('-', (PRUint32)pos)) != kNotFound) { - ++pos; - if (((PRUint32)pos == length) || (value.CharAt(pos) == '-')) { - value.Insert(PRUnichar(' '), pos++); - ++length; - } - } - NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); - aPs->mResultHandler->comment(value); - } - // xsl:copy - else if (localName == txXSLTAtoms::copy) { - xslCopy(actionElement, aPs); - } - // xsl:copy-of - else if (localName == txXSLTAtoms::copyOf) { - expr = aPs->getExpr(actionElement, ProcessorState::SelectAttr); - if (!expr) { - return; - } - - ExprResult* exprResult = expr->evaluate(aPs->getEvalContext()); - xslCopyOf(exprResult, aPs); - delete exprResult; - } - // xsl:element - else if (localName == txXSLTAtoms::element) { - nsAutoString nameAttr; - if (!actionElement->getAttr(txXSLTAtoms::name, - kNameSpaceID_None, nameAttr)) { - aPs->receiveError(NS_LITERAL_STRING("missing required name attribute for xsl:element"), NS_ERROR_FAILURE); - return; - } - - // Process name as an AttributeValueTemplate - nsAutoString name; - aPs->processAttrValueTemplate(nameAttr, actionElement, name); - - // Check name validity (must be valid QName and not xmlns) - if (!XMLUtils::isValidQName(name)) { - aPs->receiveError(NS_LITERAL_STRING("error processing xsl:element, '") + - name + NS_LITERAL_STRING("' is not a valid QName."), - NS_ERROR_FAILURE); - // XXX We should processChildren without creating attributes or - // namespace nodes. - return; - } - - // Determine namespace URI from the namespace attribute or - // from the prefix of the name (using the xslt action element). - nsAutoString resultNs; - PRInt32 resultNsID; - if (actionElement->getAttr(txXSLTAtoms::_namespace, kNameSpaceID_None, resultNs)) { - nsAutoString nsURI; - aPs->processAttrValueTemplate(resultNs, actionElement, nsURI); - if (nsURI.IsEmpty()) - resultNsID = kNameSpaceID_None; - else - resultNsID = aPs->getStylesheetDocument()->namespaceURIToID(nsURI); - } - else { - nsCOMPtr prefix; - XMLUtils::getPrefix(name, getter_AddRefs(prefix)); - resultNsID = actionElement->lookupNamespaceID(prefix); - } - - if (resultNsID == kNameSpaceID_Unknown) { - aPs->receiveError(NS_LITERAL_STRING("error processing xsl:element, can't resolve prefix on'") + - name + NS_LITERAL_STRING("'."), - NS_ERROR_FAILURE); - // XXX We should processChildren without creating attributes or - // namespace nodes. - return; - } - - NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); - aPs->mResultHandler->startElement(name, resultNsID); - processAttributeSets(actionElement, aPs); - processChildren(actionElement, aPs); - NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); - aPs->mResultHandler->endElement(name, resultNsID); - } - // xsl:for-each - else if (localName == txXSLTAtoms::forEach) { - expr = aPs->getExpr(actionElement, ProcessorState::SelectAttr); - if (!expr) { - return; - } - - ExprResult* exprResult = expr->evaluate(aPs->getEvalContext()); - if (!exprResult) { - return; - } - - if (exprResult->getResultType() == ExprResult::NODESET) { - NodeSet* nodeSet = (NodeSet*)exprResult; - if (nodeSet->isEmpty()) { - delete nodeSet; - return; - } - txNodeSetContext evalContext(nodeSet, aPs); - txIEvalContext* priorEC = - aPs->setEvalContext(&evalContext); - - // Look for xsl:sort elements - txNodeSorter sorter(aPs); - Node* child = actionElement->getFirstChild(); - while (child) { - unsigned short nodeType = child->getNodeType(); - if (nodeType == Node::ELEMENT_NODE) { - nsCOMPtr childLocalName; - child->getLocalName(getter_AddRefs(childLocalName)); - if (child->getNamespaceID() != kNameSpaceID_XSLT || - childLocalName != txXSLTAtoms::sort) { - // xsl:sort must occur first - break; - } - sorter.addSortElement((Element*)child); - } - else if ((nodeType == Node::TEXT_NODE || - nodeType == Node::CDATA_SECTION_NODE) && - !XMLUtils::isWhitespace(child)) { - break; - } - - child = child->getNextSibling(); - } - sorter.sortNodeSet(nodeSet); - - // Set current template to null - ProcessorState::TemplateRule *oldTemplate; - oldTemplate = aPs->getCurrentTemplateRule(); - aPs->setCurrentTemplateRule(0); - - while (evalContext.hasNext()) { - evalContext.next(); - processChildren(actionElement, aPs); - } - - aPs->setCurrentTemplateRule(oldTemplate); - aPs->setEvalContext(priorEC); - } - else { - aPs->receiveError(NS_LITERAL_STRING("error processing for-each"), - NS_ERROR_FAILURE); - } - //-- clean up exprResult - delete exprResult; - } - // xsl:if - else if (localName == txXSLTAtoms::_if) { - expr = aPs->getExpr(actionElement, ProcessorState::TestAttr); - if (!expr) { - return; - } - - ExprResult* exprResult = expr->evaluate(aPs->getEvalContext()); - if (!exprResult) { - return; - } - - if (exprResult->booleanValue()) { - processChildren(actionElement, aPs); - } - delete exprResult; - } - // xsl:message - else if (localName == txXSLTAtoms::message) { - nsAutoString message; - processChildrenAsValue(actionElement, aPs, MB_FALSE, message); - // We should add a MessageObserver class - logMessage(message); - } - // xsl:number - else if (localName == txXSLTAtoms::number) { - nsAutoString result; - // XXX ErrorReport, propagate result from ::createNumber - txXSLTNumber::createNumber(actionElement, aPs, result); - NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); - aPs->mResultHandler->characters(result, PR_FALSE); - } - // xsl:param - else if (localName == txXSLTAtoms::param) { - aPs->receiveError(NS_LITERAL_STRING("misplaced xsl:param"), - NS_ERROR_FAILURE); - } - // xsl:processing-instruction - else if (localName == txXSLTAtoms::processingInstruction) { - nsAutoString nameAttr; - if (!actionElement->getAttr(txXSLTAtoms::name, - kNameSpaceID_None, nameAttr)) { - aPs->receiveError(NS_LITERAL_STRING("missing required name attribute for xsl:processing-instruction"), NS_ERROR_FAILURE); - return; - } - - // Process name as an AttributeValueTemplate - nsAutoString name; - aPs->processAttrValueTemplate(nameAttr, actionElement, name); - - // Check name validity (must be valid NCName and a PITarget) - // XXX Need to check for NCName and PITarget - if (!XMLUtils::isValidQName(name)) { - aPs->receiveError(NS_LITERAL_STRING("error processing xsl:processing-instruction, '") + - name + NS_LITERAL_STRING("' is not a valid QName."), - NS_ERROR_FAILURE); - } - - // Compute value - nsAutoString value; - processChildrenAsValue(actionElement, aPs, MB_TRUE, value); - XMLUtils::normalizePIValue(value); - NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); - aPs->mResultHandler->processingInstruction(name, value); - } - // xsl:sort - else if (localName == txXSLTAtoms::sort) { - // Ignore in this loop - } - // xsl:text - else if (localName == txXSLTAtoms::text) { - nsAutoString data; - XMLDOMUtils::getNodeValue(actionElement, data); - - NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); - nsAutoString attrValue; - PRBool doe = actionElement->getAttr(txXSLTAtoms::disableOutputEscaping, - kNameSpaceID_None, attrValue) && - TX_StringEqualsAtom(attrValue, txXSLTAtoms::yes); - aPs->mResultHandler->characters(data, doe); - } - // xsl:value-of - else if (localName == txXSLTAtoms::valueOf) { - expr = aPs->getExpr(actionElement, ProcessorState::SelectAttr); - if (!expr) { - return; - } - - ExprResult* exprResult = expr->evaluate(aPs->getEvalContext()); - nsAutoString value; - if (!exprResult) { - aPs->receiveError(NS_LITERAL_STRING("null ExprResult"), - NS_ERROR_FAILURE); - return; - } - exprResult->stringValue(value); - if (value.IsEmpty()) { - delete exprResult; - return; - } - - NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); - nsAutoString attValue; - PRBool doe = actionElement->getAttr(txXSLTAtoms::disableOutputEscaping, - kNameSpaceID_None, attValue) && - TX_StringEqualsAtom(attValue, txXSLTAtoms::yes); - aPs->mResultHandler->characters(value, doe); - delete exprResult; - } - // xsl:variable - else if (localName == txXSLTAtoms::variable) { - txExpandedName varName; - nsAutoString qName; - actionElement->getAttr(txXSLTAtoms::name, kNameSpaceID_None, - qName); - rv = varName.init(qName, actionElement, MB_FALSE); - if (NS_FAILED(rv)) { - aPs->receiveError(NS_LITERAL_STRING("bad name for xsl:variable"), - NS_ERROR_FAILURE); - return; - } - ExprResult* exprResult = processVariable(actionElement, aPs); - if (!exprResult) { - return; - } - - txVariableMap* vars = aPs->getLocalVariables(); - NS_ASSERTION(vars, "missing localvariable map"); - rv = vars->bindVariable(varName, exprResult, MB_TRUE); - if (NS_FAILED(rv)) { - aPs->receiveError(NS_LITERAL_STRING("bad name for xsl:variable"), - NS_ERROR_FAILURE); - } - } -} - -void -txXSLTProcessor::processAttributeSets(Element* aElement, - ProcessorState* aPs, - txStack* aRecursionStack) -{ - nsresult rv = NS_OK; - nsAutoString names; - PRInt32 namespaceID; - if (aElement->getNamespaceID() == kNameSpaceID_XSLT) - namespaceID = kNameSpaceID_None; - else - namespaceID = kNameSpaceID_XSLT; - if (!aElement->getAttr(txXSLTAtoms::useAttributeSets, namespaceID, names) || names.IsEmpty()) - return; - - // Split names - txTokenizer tokenizer(names); - while (tokenizer.hasMoreTokens()) { - txExpandedName name; - rv = name.init(tokenizer.nextToken(), aElement, MB_FALSE); - if (NS_FAILED(rv)) { - aPs->receiveError(NS_LITERAL_STRING("missing or malformed name in use-attribute-sets")); - return; - } - - if (aRecursionStack) { - txStackIterator attributeSets(aRecursionStack); - while (attributeSets.hasNext()) { - if (name == *(txExpandedName*)attributeSets.next()) { - aPs->receiveError(NS_LITERAL_STRING("circular inclusion detected in use-attribute-sets")); - return; - } - } - } - - NodeSet* attSet = aPs->getAttributeSet(name); - if (attSet) { - int i; - //-- issue: we still need to handle the following fix cleaner, since - //-- attribute sets are merged, a different parent could exist - //-- for different xsl:attribute nodes. I will probably create - //-- an AttributeSet object, which will handle this case better. - Keith V. - if (attSet->size() > 0) { - Element* parent = (Element*) attSet->get(0)->getXPathParent(); - if (aRecursionStack) { - aRecursionStack->push(&name); - processAttributeSets(parent, aPs, aRecursionStack); - aRecursionStack->pop(); - } - else { - txStack recursionStack; - recursionStack.push(&name); - processAttributeSets(parent, aPs, &recursionStack); - recursionStack.pop(); - } - } - for (i = 0; i < attSet->size(); i++) - processAction(attSet->get(i), aPs); - delete attSet; - } - } -} - -void -txXSLTProcessor::processChildren(Element* aElement, - ProcessorState* aPs) -{ - NS_ASSERTION(aElement, "missing aElement"); - - txVariableMap* oldVars = aPs->getLocalVariables(); - txVariableMap localVars(oldVars); - aPs->setLocalVariables(&localVars); - Node* child = aElement->getFirstChild(); - while (child) { - processAction(child, aPs); - child = child->getNextSibling(); - } - aPs->setLocalVariables(oldVars); -} - -void -txXSLTProcessor::processChildrenAsValue(Element* aElement, - ProcessorState* aPs, - MBool aOnlyText, - nsAString& aValue) -{ - txAXMLEventHandler* previousHandler = aPs->mResultHandler; - txTextHandler valueHandler(aValue, aOnlyText); - aPs->mResultHandler = &valueHandler; - processChildren(aElement, aPs); - aPs->mResultHandler = previousHandler; -} - -void -txXSLTProcessor::processDefaultTemplate(ProcessorState* aPs, - const txExpandedName& aMode) -{ - Node* node = aPs->getEvalContext()->getContextNode(); - switch (node->getNodeType()) - { - case Node::ELEMENT_NODE : - case Node::DOCUMENT_NODE : - { - if (!gNodeExpr) - break; - - ExprResult* exprResult = gNodeExpr->evaluate(aPs->getEvalContext()); - if (!exprResult || - exprResult->getResultType() != ExprResult::NODESET) { - aPs->receiveError(NS_LITERAL_STRING("None-nodeset returned while processing default template"), NS_ERROR_FAILURE); - delete exprResult; - return; - } - - NodeSet* nodeSet = (NodeSet*)exprResult; - if (nodeSet->isEmpty()) { - delete nodeSet; - return; - } - txNodeSetContext evalContext(nodeSet, aPs); - txIEvalContext* priorEC = aPs->setEvalContext(&evalContext); - - while (evalContext.hasNext()) { - evalContext.next(); - Node* currNode = evalContext.getContextNode(); - - ProcessorState::ImportFrame *frame; - Node* xslTemplate = aPs->findTemplate(currNode, aMode, &frame); - processMatchedTemplate(xslTemplate, 0, aMode, frame, aPs); - } - aPs->setEvalContext(priorEC); - delete exprResult; - break; - } - case Node::ATTRIBUTE_NODE : - case Node::TEXT_NODE : - case Node::CDATA_SECTION_NODE : - { - nsAutoString nodeValue; - node->getNodeValue(nodeValue); - NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); - aPs->mResultHandler->characters(nodeValue, PR_FALSE); - break; - } - default: - // on all other nodetypes (including namespace nodes) - // we do nothing - break; - } -} - -void -txXSLTProcessor::processInclude(const nsAString& aHref, - txListIterator* aImportFrame, - ProcessorState* aPs) -{ - // make sure the include isn't included yet - nsStringArray& stylesheetStack = aPs->getEnteredStylesheets(); - if (stylesheetStack.IndexOf(aHref) != -1) { - aPs->receiveError(NS_LITERAL_STRING("Stylesheet includes itself. URI: ") + - aHref, NS_ERROR_FAILURE); - return; - } - stylesheetStack.AppendString(aHref); - - // Load XSL document - Node* stylesheet = aPs->retrieveDocument(aHref, NS_LITERAL_STRING("")); - if (!stylesheet) { - aPs->receiveError(NS_LITERAL_STRING("Unable to load included stylesheet ") + - aHref, NS_ERROR_FAILURE); - stylesheetStack.RemoveStringAt(stylesheetStack.Count() - 1); - return; - } - - switch(stylesheet->getNodeType()) { - case Node::DOCUMENT_NODE : - processStylesheet((Document*)stylesheet, 0, - aImportFrame, aPs); - break; - case Node::ELEMENT_NODE : - processTopLevel((Element*)stylesheet, 0, - aImportFrame, aPs); - break; - default: - // This should never happen - aPs->receiveError(NS_LITERAL_STRING("Unsupported fragment identifier"), NS_ERROR_FAILURE); - break; - } - - stylesheetStack.RemoveStringAt(stylesheetStack.Count() - 1); -} - -void -txXSLTProcessor::processMatchedTemplate(Node* aTemplate, - txVariableMap* aParams, - const txExpandedName& aMode, - ProcessorState::ImportFrame* aFrame, - ProcessorState* aPs) -{ - if (aTemplate) { - ProcessorState::TemplateRule *oldTemplate, newTemplate; - oldTemplate = aPs->getCurrentTemplateRule(); - newTemplate.mFrame = aFrame; - newTemplate.mMode = &aMode; - newTemplate.mParams = aParams; - aPs->setCurrentTemplateRule(&newTemplate); - - processTemplate(aTemplate, aParams, aPs); - - aPs->setCurrentTemplateRule(oldTemplate); - } - else { - processDefaultTemplate(aPs, aMode); - } -} - -nsresult -txXSLTProcessor::processParameters(Element* aAction, - txVariableMap* aMap, - ProcessorState* aPs) -{ - NS_ASSERTION(aAction && aMap, "missing argument"); - nsresult rv = NS_OK; - - Node* tmpNode = aAction->getFirstChild(); - while (tmpNode) { - if (tmpNode->getNodeType() == Node::ELEMENT_NODE && - tmpNode->getNamespaceID() == kNameSpaceID_XSLT) { - nsCOMPtr localName; - tmpNode->getLocalName(getter_AddRefs(localName)); - if (localName != txXSLTAtoms::withParam) { - tmpNode = tmpNode->getNextSibling(); - continue; - } - - Element* action = (Element*)tmpNode; - txExpandedName paramName; - nsAutoString qName; - action->getAttr(txXSLTAtoms::name, kNameSpaceID_None, qName); - rv = paramName.init(qName, action, MB_FALSE); - if (NS_FAILED(rv)) { - aPs->receiveError(NS_LITERAL_STRING("bad name for xsl:param"), - NS_ERROR_FAILURE); - break; - } - - ExprResult* exprResult = processVariable(action, aPs); - if (!exprResult) { - return NS_ERROR_FAILURE; - } - - rv = aMap->bindVariable(paramName, exprResult, MB_TRUE); - if (NS_FAILED(rv)) { - aPs->receiveError(NS_LITERAL_STRING("Unable to bind parameter '") + - qName + NS_LITERAL_STRING("'"), - NS_ERROR_FAILURE); - return rv; - } - } - tmpNode = tmpNode->getNextSibling(); - } - 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 -txXSLTProcessor::processStylesheet(Document* aStylesheet, - txExpandedNameMap* aGlobalParams, - txListIterator* aImportFrame, - ProcessorState* aPs) -{ - NS_ASSERTION(aStylesheet, "processTopLevel called without stylesheet"); - if (!aStylesheet || !aStylesheet->getDocumentElement()) - return; - - Element* elem = aStylesheet->getDocumentElement(); - - nsCOMPtr localName; - PRInt32 namespaceID = elem->getNamespaceID(); - elem->getLocalName(getter_AddRefs(localName)); - - if (((localName == txXSLTAtoms::stylesheet) || - (localName == txXSLTAtoms::transform)) && - (namespaceID == kNameSpaceID_XSLT)) { - processTopLevel(elem, aGlobalParams, aImportFrame, aPs); - } - else { - NS_ASSERTION(aImportFrame->current(), "no current importframe"); - if (!aImportFrame->current()) { - return; - } - aPs->addLREStylesheet(aStylesheet, - (ProcessorState::ImportFrame*)aImportFrame->current()); - } -} - -void -txXSLTProcessor::processTemplate(Node* aTemplate, - txVariableMap* aParams, - ProcessorState* aPs) -{ - NS_ASSERTION(aTemplate, "aTemplate is NULL"); - - nsresult rv; - - txVariableMap* oldVars = aPs->getLocalVariables(); - txVariableMap localVars(0); - aPs->setLocalVariables(&localVars); - - // handle params - Node* tmpNode = aTemplate->getFirstChild(); - while (tmpNode) { - int nodeType = tmpNode->getNodeType(); - if (nodeType == Node::ELEMENT_NODE) { - nsCOMPtr localName; - tmpNode->getLocalName(getter_AddRefs(localName)); - if (tmpNode->getNamespaceID() != kNameSpaceID_XSLT || - localName != txXSLTAtoms::param) { - break; - } - - Element* action = (Element*)tmpNode; - txExpandedName paramName; - nsAutoString qName; - action->getAttr(txXSLTAtoms::name, kNameSpaceID_None, qName); - rv = paramName.init(qName, action, MB_FALSE); - if (NS_FAILED(rv)) { - aPs->receiveError(NS_LITERAL_STRING("bad name for xsl:param"), - NS_ERROR_FAILURE); - break; - } - - ExprResult* exprResult; - if (aParams && (exprResult = aParams->getVariable(paramName))) { - rv = localVars.bindVariable(paramName, exprResult, MB_FALSE); - } - else { - exprResult = processVariable(action, aPs); - if (!exprResult) - break; - rv = localVars.bindVariable(paramName, exprResult, MB_TRUE); - } - - if (NS_FAILED(rv)) { - aPs->receiveError(NS_LITERAL_STRING("unable to bind xsl:param"), - NS_ERROR_FAILURE); - } - - } - else if (!(nodeType == Node::COMMENT_NODE || - ((nodeType == Node::TEXT_NODE || - nodeType == Node::CDATA_SECTION_NODE) && - XMLUtils::isWhitespace(tmpNode)))) { - break; - } - tmpNode = tmpNode->getNextSibling(); - } - - // execute contents - while (tmpNode) { - processAction(tmpNode, aPs); - tmpNode = tmpNode->getNextSibling(); - } - aPs->setLocalVariables(oldVars); -} - -nsresult -txXSLTProcessor::processTopLevel(Element* aStylesheet, - txExpandedNameMap* aGlobalParams, - ProcessorState* aPs) -{ - 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; -} - -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; - - ProcessorState::ImportFrame* currentFrame = - (ProcessorState::ImportFrame*)importFrame->current(); - - NS_ASSERTION(currentFrame, - "processTopLevel called with no current importframe"); - if (!currentFrame) - return; - - MBool importsDone = MB_FALSE; - Node* node = aStylesheet->getFirstChild(); - while (node && !importsDone) { - if (node->getNodeType() == Node::ELEMENT_NODE) { - nsCOMPtr localName; - node->getLocalName(getter_AddRefs(localName)); - if (node->getNamespaceID() == kNameSpaceID_XSLT && - localName == txXSLTAtoms::import) { - Element* element = (Element*)node; - nsAutoString hrefAttr, href, baseURI; - element->getAttr(txXSLTAtoms::href, kNameSpaceID_None, - hrefAttr); - element->getBaseURI(baseURI); - URIUtils::resolveHref(hrefAttr, baseURI, - href); - - // Create a new ImportFrame with correct firstNotImported - ProcessorState::ImportFrame *nextFrame, *newFrame; - nextFrame = - (ProcessorState::ImportFrame*)importFrame->next(); - newFrame = new ProcessorState::ImportFrame(nextFrame); - if (!newFrame) { - // XXX ErrorReport: out of memory - break; - } - - // Insert frame and process stylesheet - importFrame->addBefore(newFrame); - importFrame->previous(); - processInclude(href, importFrame, aPs); - - // Restore iterator to initial position - importFrame->previous(); - } - else { - importsDone = MB_TRUE; - } - } - if (!importsDone) - node = node->getNextSibling(); - } - - while (node) { - if (node->getNodeType() != Node::ELEMENT_NODE || - node->getNamespaceID() != kNameSpaceID_XSLT) { - node = node->getNextSibling(); - continue; - } - - nsCOMPtr localName; - node->getLocalName(getter_AddRefs(localName)); - Element* element = (Element*)node; - // xsl:attribute-set - if (localName == txXSLTAtoms::attributeSet) { - aPs->addAttributeSet(element, currentFrame); - } - // xsl:decimal-format - else if (localName == txXSLTAtoms::decimalFormat) { - if (!aPs->addDecimalFormat(element)) { - // Add error to ErrorObserver - nsAutoString fName; - element->getAttr(txXSLTAtoms::name, kNameSpaceID_None, - fName); - nsAutoString err(NS_LITERAL_STRING("unable to add ")); - if (fName.IsEmpty()) { - err.Append(NS_LITERAL_STRING("default")); - } - else { - err.Append(PRUnichar('\"')); - err.Append(fName); - err.Append(PRUnichar('\"')); - } - err.Append(NS_LITERAL_STRING(" decimal format for xsl:decimal-format")); - aPs->receiveError(err, NS_ERROR_FAILURE); - } - } - // xsl:param - else if (localName == txXSLTAtoms::param) { - nsAutoString 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)) { - aPs->receiveError(NS_LITERAL_STRING("unable to add global xsl:param"), NS_ERROR_FAILURE); - } - } - else { - aPs->receiveError(NS_LITERAL_STRING("unable to add global xsl:param"), NS_ERROR_FAILURE); - } - } - // xsl:import - else if (localName == txXSLTAtoms::import) { - aPs->receiveError(NS_LITERAL_STRING("xsl:import only allowed at top of stylesheet"), NS_ERROR_FAILURE); - } - // xsl:include - else if (localName == txXSLTAtoms::include) { - nsAutoString hrefAttr, href, baseURI; - element->getAttr(txXSLTAtoms::href, kNameSpaceID_None, - hrefAttr); - element->getBaseURI(baseURI); - URIUtils::resolveHref(hrefAttr, baseURI, - href); - - processInclude(href, importFrame, aPs); - } - // xsl:key - else if (localName == txXSLTAtoms::key) { - if (!aPs->addKey(element)) { - nsAutoString name; - element->getAttr(txXSLTAtoms::name, kNameSpaceID_None, - name); - aPs->receiveError(NS_LITERAL_STRING("error adding key '") + - name + NS_LITERAL_STRING("'"), - NS_ERROR_FAILURE); - } - } - // xsl:output - else if (localName == txXSLTAtoms::output) { - txOutputFormat& format = currentFrame->mOutputFormat; - nsAutoString attValue; - - if (element->getAttr(txXSLTAtoms::method, kNameSpaceID_None, - attValue)) { - if (attValue.Equals(NS_LITERAL_STRING("html"))) { - format.mMethod = eHTMLOutput; - } - else if (attValue.Equals(NS_LITERAL_STRING("text"))) { - format.mMethod = eTextOutput; - } - else { - format.mMethod = eXMLOutput; - } - } - - if (element->getAttr(txXSLTAtoms::version, kNameSpaceID_None, - attValue)) { - format.mVersion = attValue; - } - - if (element->getAttr(txXSLTAtoms::encoding, kNameSpaceID_None, - attValue)) { - format.mEncoding = attValue; - } - - if (element->getAttr(txXSLTAtoms::omitXmlDeclaration, - kNameSpaceID_None, attValue)) { - format.mOmitXMLDeclaration = - TX_StringEqualsAtom(attValue, txXSLTAtoms::yes) ? eTrue : eFalse; - } - - if (element->getAttr(txXSLTAtoms::standalone, kNameSpaceID_None, - attValue)) { - format.mStandalone = - TX_StringEqualsAtom(attValue, txXSLTAtoms::yes) ? eTrue : eFalse; - } - - if (element->getAttr(txXSLTAtoms::doctypePublic, - kNameSpaceID_None, attValue)) { - format.mPublicId = attValue; - } - - if (element->getAttr(txXSLTAtoms::doctypeSystem, - kNameSpaceID_None, attValue)) { - format.mSystemId = attValue; - } - - if (element->getAttr(txXSLTAtoms::cdataSectionElements, - kNameSpaceID_None, attValue)) { - txTokenizer tokens(attValue); - while (tokens.hasMoreTokens()) { - txExpandedName* qname = new txExpandedName(); - if (!qname || NS_FAILED(qname->init(tokens.nextToken(), - element, PR_FALSE))) { - // XXX ErrorReport - break; - } - format.mCDATASectionElements.add(qname); - } - } - - if (element->getAttr(txXSLTAtoms::indent, kNameSpaceID_None, - attValue)) { - format.mIndent = - TX_StringEqualsAtom(attValue, txXSLTAtoms::yes) ? eTrue : eFalse; - } - - if (element->getAttr(txXSLTAtoms::mediaType, kNameSpaceID_None, - attValue)) { - format.mMediaType = attValue; - } - } - // xsl:template - else if (localName == txXSLTAtoms::_template) { - aPs->addTemplate(element, currentFrame); - } - // xsl:variable - else if (localName == txXSLTAtoms::variable) { - nsAutoString 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)) { - aPs->receiveError(NS_LITERAL_STRING("unable to add global xsl:variable"), NS_ERROR_FAILURE); - } - } - else { - aPs->receiveError(NS_LITERAL_STRING("unable to add global xsl:variable"), NS_ERROR_FAILURE); - } - } - // xsl:preserve-space - else if (localName == txXSLTAtoms::preserveSpace) { - nsAutoString elements; - if (!element->getAttr(txXSLTAtoms::elements, - kNameSpaceID_None, elements)) { - //-- add error to ErrorObserver - aPs->receiveError(NS_LITERAL_STRING("missing required 'elements' attribute for xsl:preserve-space"), NS_ERROR_FAILURE); - } - else { - aPs->shouldStripSpace(elements, element, - MB_FALSE, - currentFrame); - } - } - // xsl:strip-space - else if (localName == txXSLTAtoms::stripSpace) { - nsAutoString elements; - if (!element->getAttr(txXSLTAtoms::elements, - kNameSpaceID_None, elements)) { - //-- add error to ErrorObserver - aPs->receiveError(NS_LITERAL_STRING("missing required 'elements' attribute for xsl:strip-space"), NS_ERROR_FAILURE); - } - else { - aPs->shouldStripSpace(elements, element, - MB_TRUE, - currentFrame); - } - } - node = node->getNextSibling(); - } -} - -ExprResult* -txXSLTProcessor::processVariable(Element* aVariable, - ProcessorState* aPs) -{ - NS_ASSERTION(aVariable, "missing xslVariable"); - - //-- check for select attribute - if (aVariable->hasAttr(txXSLTAtoms::select, kNameSpaceID_None)) { - Expr* expr = aPs->getExpr(aVariable, ProcessorState::SelectAttr); - if (!expr) - return new StringResult(NS_LITERAL_STRING("unable to process variable")); - return expr->evaluate(aPs->getEvalContext()); - } - if (aVariable->hasChildNodes()) { - txAXMLEventHandler* previousHandler = aPs->mResultHandler; - - txRtfHandler rtfHandler; - txResultTreeFragment* rtf = rtfHandler.createRTF(); - if (!rtf) { - // ErrorReport: out of memory - return nsnull; - } - - aPs->mResultHandler = &rtfHandler; - processChildren(aVariable, aPs); - NS_ASSERTION(previousHandler, "Setting mResultHandler to NULL!"); - aPs->mResultHandler = previousHandler; - return rtf; - } - return new StringResult(); -} - -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())) { - outputFormat->merge(frame->mOutputFormat); - } - - txAXMLEventHandler* handler = 0; - rv = aPs->mOutputHandlerFactory->createHandlerWith(aPs->getOutputFormat(), - &handler); - if (NS_FAILED(rv)) { - return; - } - aPs->mOutputHandler = handler; - aPs->mResultHandler = handler; - aPs->mOutputHandler->startDocument(); - - frame = 0; - txExpandedName nullMode; - Node* xslTemplate = aPs->findTemplate(aPs->getEvalContext()->getContextNode(), - nullMode, &frame); - processMatchedTemplate(xslTemplate, 0, nullMode, frame, aPs); - - aPs->mOutputHandler->endDocument(); -} - -void -txXSLTProcessor::xslCopy(Element* aAction, ProcessorState* aPs) -{ - Node* node = aPs->getEvalContext()->getContextNode(); - - switch (node->getNodeType()) { - case Node::DOCUMENT_NODE: - { - // Just process children - processChildren(aAction, aPs); - break; - } - case Node::ELEMENT_NODE: - { - Element* element = (Element*)node; - nsAutoString nodeName; - element->getNodeName(nodeName); - PRInt32 nsID = element->getNamespaceID(); - - 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(aPs->mResultHandler, "mResultHandler must not be NULL!"); - aPs->mResultHandler->endElement(nodeName, nsID); - break; - } - default: - { - copyNode(node, aPs); - } - } -} - -void -txXSLTProcessor::xslCopyOf(ExprResult* aExprResult, ProcessorState* aPs) -{ - if (!aExprResult) - return; - - switch (aExprResult->getResultType()) { - case ExprResult::NODESET: - { - NodeSet* nodes = (NodeSet*)aExprResult; - int i; - for (i = 0; i < nodes->size(); i++) { - Node* node = nodes->get(i); - copyNode(node, aPs); - } - break; - } - case ExprResult::RESULT_TREE_FRAGMENT: - { - txResultTreeFragment* rtf = NS_STATIC_CAST(txResultTreeFragment*, - aExprResult); - NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); - rtf->flushToHandler(aPs->mResultHandler); - break; - } - default: - { - nsAutoString value; - aExprResult->stringValue(value); - NS_ASSERTION(aPs->mResultHandler, "mResultHandler must not be NULL!"); - aPs->mResultHandler->characters(value, PR_FALSE); - } - } -} diff --git a/mozilla/extensions/transformiix/source/xslt/XSLTProcessor.h b/mozilla/extensions/transformiix/source/xslt/XSLTProcessor.h deleted file mode 100644 index 8ec386174ef..00000000000 --- a/mozilla/extensions/transformiix/source/xslt/XSLTProcessor.h +++ /dev/null @@ -1,267 +0,0 @@ -/* -*- 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 - * 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 The MITRE Corporation. - * Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation. - * - * Portions created by Keith Visco as a Non MITRE employee, - * (C) 1999 Keith Visco. All Rights Reserved. - * - * Contributor(s): - * Keith Visco, kvisco@ziplink.net - * -- original author. - * - */ - - -#ifndef TRANSFRMX_XSLTPROCESSOR_H -#define TRANSFRMX_XSLTPROCESSOR_H - -#include "ProcessorState.h" - -class txStack; - -class txIGlobalParameter : public TxObject -{ -public: - virtual nsresult getValue(ExprResult** aValue) = 0; -}; - -/** - * A class for Processing XSLT Stylesheets - */ -class txXSLTProcessor -{ -public: - /** - * Initialisation and shutdown routines - * Allocate and free static atoms. - */ - static MBool txInit(); - static MBool txShutdown(); - - /** - * 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); - - /** - * 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); - - /** - * Transforms a node. - * - * @param aPs the current ProcessorState with the node - * as current node and the desired templates - */ - static void transform(ProcessorState* aPs); - -private: - /** - * Copy a node. For document nodes, copy the children. - * - * @param aSourceNode node to copy - * @param aPs the current ProcessorState - */ - static void copyNode(Node* aSourceNode, ProcessorState* aPs); - - /** - * Log a message. - * - * @param aMessage the message to log - */ - static void logMessage(const nsAString& 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, - txStack* 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, - nsAString& 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(const nsAString& 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) - * @param aMap map to place parsed variables in - * @param aPs the current ProcessorState - * @return errorcode - */ - static nsresult processParameters(Element* aAction, txVariableMap* aMap, - 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. 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 - */ - static void processTemplate(Node* aTemplate, txVariableMap* aParams, - ProcessorState* aPs); - - /** - * 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 - */ - static void processTopLevel(Element* aStylesheet, - txExpandedNameMap* aGlobalParams, - txListIterator* aImportFrame, - ProcessorState* aPs); - - /** - * Processes the given xsl:variable. - * - * @param aVariable the variable element - * @param aPs the current ProcessorState - */ - static ExprResult* processVariable(Element* aVariable, - 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); - - /** - * 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); - - /** - * Used as default expression for some elements - */ - static Expr* gNodeExpr; - - friend class ProcessorState; -}; - -#endif diff --git a/mozilla/extensions/transformiix/source/xslt/functions/CurrentFunctionCall.cpp b/mozilla/extensions/transformiix/source/xslt/functions/CurrentFunctionCall.cpp index 322eb334913..58de21ff130 100644 --- a/mozilla/extensions/transformiix/source/xslt/functions/CurrentFunctionCall.cpp +++ b/mozilla/extensions/transformiix/source/xslt/functions/CurrentFunctionCall.cpp @@ -1,6 +1,6 @@ -#include "ProcessorState.h" #include "txAtoms.h" #include "XSLTFunctions.h" +#include "txExecutionState.h" /* Implementation of XSLT 1.0 extension function: current @@ -9,8 +9,7 @@ /** * Creates a new current function call **/ -CurrentFunctionCall::CurrentFunctionCall(ProcessorState* aPs) - : mPs(aPs) +CurrentFunctionCall::CurrentFunctionCall() { } @@ -22,7 +21,16 @@ CurrentFunctionCall::CurrentFunctionCall(ProcessorState* aPs) */ ExprResult* CurrentFunctionCall::evaluate(txIEvalContext* aContext) { - return new NodeSet(mPs->getEvalContext()->getContextNode()); + txExecutionState* es = + NS_STATIC_CAST(txExecutionState*, aContext->getPrivateContext()); + if (!es) { + NS_ASSERTION(0, + "called xslt extension function \"current\" with wrong context"); + // Just return an empty nodeset, this at least has the right + // result type. + return new NodeSet(); + } + return new NodeSet(es->getEvalContext()->getContextNode()); } nsresult CurrentFunctionCall::getNameAtom(nsIAtom** aAtom) diff --git a/mozilla/extensions/transformiix/source/xslt/functions/DocumentFunctionCall.cpp b/mozilla/extensions/transformiix/source/xslt/functions/DocumentFunctionCall.cpp index 61a1da3bbcc..4ca2b181879 100644 --- a/mozilla/extensions/transformiix/source/xslt/functions/DocumentFunctionCall.cpp +++ b/mozilla/extensions/transformiix/source/xslt/functions/DocumentFunctionCall.cpp @@ -36,19 +36,17 @@ * A representation of the XSLT additional function: document() */ -#include "ProcessorState.h" #include "txAtoms.h" #include "txIXPathContext.h" #include "XMLDOMUtils.h" #include "XSLTFunctions.h" +#include "txExecutionState.h" /* * Creates a new DocumentFunctionCall. */ -DocumentFunctionCall::DocumentFunctionCall(ProcessorState* aPs, - Node* aDefResolveNode) - : mProcessorState(aPs), - mDefResolveNode(aDefResolveNode) +DocumentFunctionCall::DocumentFunctionCall(const nsAString& aBaseURI) + : mBaseURI(aBaseURI) { } @@ -61,7 +59,11 @@ DocumentFunctionCall::DocumentFunctionCall(ProcessorState* aPs, */ ExprResult* DocumentFunctionCall::evaluate(txIEvalContext* aContext) { + txExecutionState* es = + NS_STATIC_CAST(txExecutionState*, aContext->getPrivateContext()); + NodeSet* nodeSet = new NodeSet(); + NS_ENSURE_TRUE(nodeSet, nsnull); // document(object, node-set?) if (requireParams(1, 2, aContext)) { @@ -110,17 +112,21 @@ ExprResult* DocumentFunctionCall::evaluate(txIEvalContext* aContext) // the baseUri of node itself node->getBaseURI(baseURI); } - nodeSet->add(mProcessorState->retrieveDocument(uriStr, baseURI)); + Node* loadNode = es->retrieveDocument(uriStr, baseURI); + if (loadNode) { + nodeSet->add(loadNode); + } } } else { // The first argument is not a NodeSet nsAutoString uriStr; exprResult1->stringValue(uriStr); - if (!baseURISet) { - mDefResolveNode->getBaseURI(baseURI); + Node* loadNode = + es->retrieveDocument(uriStr, baseURISet ? baseURI : mBaseURI); + if (loadNode) { + nodeSet->add(loadNode); } - nodeSet->add(mProcessorState->retrieveDocument(uriStr, baseURI)); } delete exprResult1; } diff --git a/mozilla/extensions/transformiix/source/xslt/functions/ElementAvailableFnCall.cpp b/mozilla/extensions/transformiix/source/xslt/functions/ElementAvailableFnCall.cpp index 45ae8c55ef4..baf3f42fb6f 100644 --- a/mozilla/extensions/transformiix/source/xslt/functions/ElementAvailableFnCall.cpp +++ b/mozilla/extensions/transformiix/source/xslt/functions/ElementAvailableFnCall.cpp @@ -41,6 +41,7 @@ #include "txAtoms.h" #include "XMLUtils.h" #include "XSLTFunctions.h" +#include "ExprResult.h" /* Implementation of XSLT 1.0 extension function: element-available @@ -51,8 +52,8 @@ * aNode is the Element in the stylesheet containing the * Expr and is used for namespaceID resolution **/ -ElementAvailableFunctionCall::ElementAvailableFunctionCall(Node* aQNameResolveNode) - : mQNameResolveNode(aQNameResolveNode) +ElementAvailableFunctionCall::ElementAvailableFunctionCall(txNamespaceMap* aMappings) + : mMappings(aMappings) { } @@ -77,7 +78,7 @@ ExprResult* ElementAvailableFunctionCall::evaluate(txIEvalContext* aContext) nsAutoString property; exprResult->stringValue(property); txExpandedName qname; - nsresult rv = qname.init(property, mQNameResolveNode, MB_TRUE); + nsresult rv = qname.init(property, mMappings, MB_TRUE); if (NS_SUCCEEDED(rv) && qname.mNamespaceID == kNameSpaceID_XSLT && (qname.mLocalName == txXSLTAtoms::applyImports || diff --git a/mozilla/extensions/transformiix/source/xslt/functions/FunctionAvailableFnCall.cpp b/mozilla/extensions/transformiix/source/xslt/functions/FunctionAvailableFnCall.cpp index 0ece240f0ba..e853fae51f8 100644 --- a/mozilla/extensions/transformiix/source/xslt/functions/FunctionAvailableFnCall.cpp +++ b/mozilla/extensions/transformiix/source/xslt/functions/FunctionAvailableFnCall.cpp @@ -41,6 +41,7 @@ #include "txAtoms.h" #include "XMLUtils.h" #include "XSLTFunctions.h" +#include "ExprResult.h" /* Implementation of XSLT 1.0 extension function: function-available @@ -49,8 +50,8 @@ /** * Creates a new function-available function call **/ -FunctionAvailableFunctionCall::FunctionAvailableFunctionCall(Node* aQNameResolveNode) - : mQNameResolveNode(aQNameResolveNode) +FunctionAvailableFunctionCall::FunctionAvailableFunctionCall(txNamespaceMap* aMappings) + : mMappings(aMappings) { } @@ -75,7 +76,7 @@ ExprResult* FunctionAvailableFunctionCall::evaluate(txIEvalContext* aContext) nsAutoString property; exprResult->stringValue(property); txExpandedName qname; - nsresult rv = qname.init(property, mQNameResolveNode, MB_FALSE); + nsresult rv = qname.init(property, mMappings, MB_FALSE); if (NS_SUCCEEDED(rv) && qname.mNamespaceID == kNameSpaceID_None && (qname.mLocalName == txXPathAtoms::boolean || diff --git a/mozilla/extensions/transformiix/source/xslt/functions/GenerateIdFunctionCall.cpp b/mozilla/extensions/transformiix/source/xslt/functions/GenerateIdFunctionCall.cpp index a91754924d0..2d23c5f929e 100644 --- a/mozilla/extensions/transformiix/source/xslt/functions/GenerateIdFunctionCall.cpp +++ b/mozilla/extensions/transformiix/source/xslt/functions/GenerateIdFunctionCall.cpp @@ -26,6 +26,7 @@ #include "txIXPathContext.h" #include "XSLTFunctions.h" #include "prprf.h" +#include "NodeSet.h" /* Implementation of XSLT 1.0 extension function: generate-id diff --git a/mozilla/extensions/transformiix/source/xslt/functions/SystemPropertyFunctionCall.cpp b/mozilla/extensions/transformiix/source/xslt/functions/SystemPropertyFunctionCall.cpp index 42bcc691f33..7261784affc 100644 --- a/mozilla/extensions/transformiix/source/xslt/functions/SystemPropertyFunctionCall.cpp +++ b/mozilla/extensions/transformiix/source/xslt/functions/SystemPropertyFunctionCall.cpp @@ -2,6 +2,7 @@ #include "txAtoms.h" #include "XMLUtils.h" #include "XSLTFunctions.h" +#include "ExprResult.h" /* Implementation of XSLT 1.0 extension function: system-property @@ -12,8 +13,8 @@ * aNode is the Element in the stylesheet containing the * Expr and is used for namespaceID resolution **/ -SystemPropertyFunctionCall::SystemPropertyFunctionCall(Node* aQNameResolveNode) - : mQNameResolveNode(aQNameResolveNode) +SystemPropertyFunctionCall::SystemPropertyFunctionCall(txNamespaceMap* aMappings) + : mMappings(aMappings) { } @@ -37,7 +38,7 @@ ExprResult* SystemPropertyFunctionCall::evaluate(txIEvalContext* aContext) nsAutoString property; exprResult->stringValue(property); txExpandedName qname; - nsresult rv = qname.init(property, mQNameResolveNode, MB_TRUE); + nsresult rv = qname.init(property, mMappings, MB_TRUE); if (NS_SUCCEEDED(rv) && qname.mNamespaceID == kNameSpaceID_XSLT) { if (qname.mLocalName == txXSLTAtoms::version) { diff --git a/mozilla/extensions/transformiix/source/xslt/functions/XSLTFunctions.h b/mozilla/extensions/transformiix/source/xslt/functions/XSLTFunctions.h index 3ac1e1340c8..0bf488d5c33 100644 --- a/mozilla/extensions/transformiix/source/xslt/functions/XSLTFunctions.h +++ b/mozilla/extensions/transformiix/source/xslt/functions/XSLTFunctions.h @@ -32,10 +32,14 @@ #define TRANSFRMX_XSLT_FUNCTIONS_H #include "Expr.h" -#include "Map.h" -#include "NodeSet.h" +#include "txNamespaceMap.h" +#include "XMLUtils.h" +#include "nsAutoPtr.h" -class ProcessorState; +class txPattern; +class txStylesheet; +class txKeyValueHashKey; +class txExecutionState; /** * The definition for the XSLT document() function @@ -47,13 +51,12 @@ public: /** * Creates a new document() function call **/ - DocumentFunctionCall(ProcessorState* aPs, Node* aDefResolveNode); + DocumentFunctionCall(const nsAString& aBaseURI); TX_DECL_FUNCTION; private: - ProcessorState* mProcessorState; - Node* mDefResolveNode; + nsString mBaseURI; }; /* @@ -66,13 +69,12 @@ public: /* * Creates a new key() function call */ - txKeyFunctionCall(ProcessorState* aPs, Node* aQNameResolveNode); + txKeyFunctionCall(txNamespaceMap* aMappings); TX_DECL_FUNCTION; private: - ProcessorState* mProcessorState; - Node* mQNameResolveNode; + nsRefPtr mMappings; }; /** @@ -85,7 +87,7 @@ public: /** * Creates a new format-number() function call **/ - txFormatNumberFunctionCall(ProcessorState* aPs, Node* aQNameResolveNode); + txFormatNumberFunctionCall(txStylesheet* aStylesheet, txNamespaceMap* aMappings); TX_DECL_FUNCTION; @@ -102,8 +104,8 @@ private: Finished }; - ProcessorState* mPs; - Node* mQNameResolveNode; + txStylesheet* mStylesheet; + nsRefPtr mMappings; }; /** @@ -142,12 +144,9 @@ public: /** * Creates a new current() function call **/ - CurrentFunctionCall(ProcessorState* ps); + CurrentFunctionCall(); TX_DECL_FUNCTION; - -private: - ProcessorState* mPs; }; /** @@ -197,7 +196,7 @@ public: * aNode is the Element in the stylesheet containing the * Expr and is used for namespaceID resolution **/ - SystemPropertyFunctionCall(Node* aQNameResolveNode); + SystemPropertyFunctionCall(txNamespaceMap* aMappings); TX_DECL_FUNCTION; @@ -205,7 +204,7 @@ private: /* * resolve namespaceIDs with this node */ - Node* mQNameResolveNode; + nsRefPtr mMappings; }; /** @@ -220,7 +219,7 @@ public: * aNode is the Element in the stylesheet containing the * Expr and is used for namespaceID resolution **/ - ElementAvailableFunctionCall(Node* aQNameResolveNode); + ElementAvailableFunctionCall(txNamespaceMap* aMappings); TX_DECL_FUNCTION; @@ -228,7 +227,7 @@ private: /* * resolve namespaceIDs with this node */ - Node* mQNameResolveNode; + nsRefPtr mMappings; }; /** @@ -241,7 +240,7 @@ public: /** * Creates a new function-available() function call **/ - FunctionAvailableFunctionCall(Node* aQNameResolveNode); + FunctionAvailableFunctionCall(txNamespaceMap* aMappings); TX_DECL_FUNCTION; @@ -249,7 +248,7 @@ private: /* * resolve namespaceIDs with this node */ - Node* mQNameResolveNode; + nsRefPtr mMappings; }; #endif diff --git a/mozilla/extensions/transformiix/source/xslt/functions/txFormatNumberFunctionCall.cpp b/mozilla/extensions/transformiix/source/xslt/functions/txFormatNumberFunctionCall.cpp index ae5f6b0a15d..64927086385 100644 --- a/mozilla/extensions/transformiix/source/xslt/functions/txFormatNumberFunctionCall.cpp +++ b/mozilla/extensions/transformiix/source/xslt/functions/txFormatNumberFunctionCall.cpp @@ -37,11 +37,12 @@ * ***** END LICENSE BLOCK ***** */ #include "XSLTFunctions.h" -#include "ProcessorState.h" #include "primitives.h" #include "txAtoms.h" #include "txIXPathContext.h" +#include "txStylesheet.h" #include +#include "ExprResult.h" #include "prdtoa.h" @@ -55,10 +56,10 @@ const PRUnichar txFormatNumberFunctionCall::FORMAT_QUOTE = '\''; /* * Creates a new format-number function call */ -txFormatNumberFunctionCall::txFormatNumberFunctionCall(ProcessorState* aPs, - Node* aQNameResolveNode) - : mPs(aPs), - mQNameResolveNode(aQNameResolveNode) +txFormatNumberFunctionCall::txFormatNumberFunctionCall(txStylesheet* aStylesheet, + txNamespaceMap* aMappings) + : mStylesheet(aStylesheet), + mMappings(aMappings) { } @@ -87,12 +88,12 @@ ExprResult* txFormatNumberFunctionCall::evaluate(txIEvalContext* aContext) if (iter.hasNext()) { nsAutoString formatQName; evaluateToString((Expr*)iter.next(), aContext, formatQName); - rv = formatName.init(formatQName, mQNameResolveNode, MB_FALSE); + rv = formatName.init(formatQName, mMappings, MB_FALSE); if (NS_FAILED(rv)) formatName.mNamespaceID = kNameSpaceID_Unknown; } - txDecimalFormat* format = mPs->getDecimalFormat(formatName); + txDecimalFormat* format = mStylesheet->getDecimalFormat(formatName); if (!format) { nsAutoString err(NS_LITERAL_STRING("unknown decimal format for: ")); toString(err); diff --git a/mozilla/extensions/transformiix/source/xslt/functions/txKey.h b/mozilla/extensions/transformiix/source/xslt/functions/txKey.h index b4e7e31e975..a2d3906a028 100644 --- a/mozilla/extensions/transformiix/source/xslt/functions/txKey.h +++ b/mozilla/extensions/transformiix/source/xslt/functions/txKey.h @@ -41,6 +41,13 @@ #include "nsDoubleHashtable.h" #include "XMLUtils.h" +#include "NodeSet.h" +#include "List.h" +#include "txXSLTPatterns.h" + +class txPattern; +class Expr; +class txExecutionState; class txKeyValueHashKey { @@ -129,17 +136,17 @@ public: * @param aUse use-expression * @return PR_FALSE if an error occured, PR_TRUE otherwise */ - PRBool addKey(txPattern* aMatch, Expr* aUse); + PRBool addKey(nsAutoPtr aMatch, nsAutoPtr aUse); /** * Indexes a document and adds it to the hash of key values * @param aDocument Document to index and add * @param aKeyValueHash Hash to add values to - * @param aPs ProcessorState to use for XPath evaluation + * @param aEs txExecutionState to use for XPath evaluation */ nsresult indexDocument(Document* aDocument, txKeyValueHash& aKeyValueHash, - ProcessorState* aPs); + txExecutionState& aEs); private: /** @@ -148,10 +155,10 @@ private: * @param aNode Node to search * @param aKey Key to use when adding into the hash * @param aKeyValueHash Hash to add values to - * @param aPs ProcessorState to use for XPath evaluation + * @param aEs txExecutionState to use for XPath evaluation */ nsresult indexTree(Node* aNode, txKeyValueHashKey& aKey, - txKeyValueHash& aKeyValueHash, ProcessorState* aPs); + txKeyValueHash& aKeyValueHash, txExecutionState& aEs); /** * Tests one node if it matches any of the keys match-patterns. If @@ -159,17 +166,17 @@ private: * @param aNode Node to test * @param aKey Key to use when adding into the hash * @param aKeyValueHash Hash to add values to - * @param aPs ProcessorState to use for XPath evaluation + * @param aEs txExecutionState to use for XPath evaluation */ nsresult testNode(Node* aNode, txKeyValueHashKey& aKey, - txKeyValueHash& aKeyValueHash, ProcessorState* aPs); + txKeyValueHash& aKeyValueHash, txExecutionState& aEs); /** * represents one match/use pair */ struct Key { - txPattern* matchPattern; - Expr* useExpr; + nsAutoPtr matchPattern; + nsAutoPtr useExpr; }; /** @@ -187,7 +194,7 @@ private: class txKeyHash { public: - txKeyHash(txExpandedNameMap& aKeys) + txKeyHash(const txExpandedNameMap& aKeys) : mKeys(aKeys) { } @@ -198,7 +205,7 @@ public: Document* aDocument, const nsAString& aKeyValue, PRBool aIndexIfNotFound, - ProcessorState* aPs, + txExecutionState& aEs, const NodeSet** aResult); private: @@ -209,7 +216,7 @@ private: txIndexedKeyHash mIndexedKeys; // Map of txXSLKeys - txExpandedNameMap& mKeys; + const txExpandedNameMap& mKeys; }; diff --git a/mozilla/extensions/transformiix/source/xslt/functions/txKeyFunctionCall.cpp b/mozilla/extensions/transformiix/source/xslt/functions/txKeyFunctionCall.cpp index b6aad29d998..b70af00fc57 100644 --- a/mozilla/extensions/transformiix/source/xslt/functions/txKeyFunctionCall.cpp +++ b/mozilla/extensions/transformiix/source/xslt/functions/txKeyFunctionCall.cpp @@ -18,13 +18,14 @@ * -- original author. */ -#include "ProcessorState.h" +#include "txExecutionState.h" #include "txAtoms.h" #include "txSingleNodeContext.h" #include "XMLDOMUtils.h" #include "XSLTFunctions.h" #include "nsReadableUtils.h" #include "txKey.h" +#include "txXSLTPatterns.h" /* * txKeyFunctionCall @@ -34,10 +35,8 @@ /* * Creates a new key function call */ -txKeyFunctionCall::txKeyFunctionCall(ProcessorState* aPs, - Node* aQNameResolveNode) - : mProcessorState(aPs), - mQNameResolveNode(aQNameResolveNode) +txKeyFunctionCall::txKeyFunctionCall(txNamespaceMap* aMappings) + : mMappings(aMappings) { } @@ -54,6 +53,9 @@ ExprResult* txKeyFunctionCall::evaluate(txIEvalContext* aContext) if (!aContext || !requireParams(2, 2, aContext)) return new StringResult(NS_LITERAL_STRING("error")); + txExecutionState* es = + NS_STATIC_CAST(txExecutionState*, aContext->getPrivateContext()); + NodeSet* res = new NodeSet; if (!res) { // ErrorReport: out of memory @@ -65,7 +67,7 @@ ExprResult* txKeyFunctionCall::evaluate(txIEvalContext* aContext) evaluateToString((Expr*)iter.next(), aContext, keyQName); txExpandedName keyName; - nsresult rv = keyName.init(keyQName, mQNameResolveNode, PR_FALSE); + nsresult rv = keyName.init(keyQName, mMappings, PR_FALSE); if (NS_FAILED(rv)) { delete res; return new StringResult(NS_LITERAL_STRING("error")); @@ -89,8 +91,7 @@ ExprResult* txKeyFunctionCall::evaluate(txIEvalContext* aContext) nsAutoString val; XMLDOMUtils::getNodeValue(nodeSet->get(i), val); const NodeSet* nodes = 0; - rv = mProcessorState->getKeyNodes(keyName, contextDoc, val, - i == 0, &nodes); + rv = es->getKeyNodes(keyName, contextDoc, val, i == 0, &nodes); if (NS_FAILED(rv)) { delete res; delete exprResult; @@ -105,8 +106,7 @@ ExprResult* txKeyFunctionCall::evaluate(txIEvalContext* aContext) nsAutoString val; exprResult->stringValue(val); const NodeSet* nodes = 0; - rv = mProcessorState->getKeyNodes(keyName, contextDoc, val, - PR_TRUE, &nodes); + rv = es->getKeyNodes(keyName, contextDoc, val, PR_TRUE, &nodes); if (NS_FAILED(rv)) { delete res; delete exprResult; @@ -199,7 +199,7 @@ txKeyHash::getKeyNodes(const txExpandedName& aKeyName, Document* aDocument, const nsAString& aKeyValue, PRBool aIndexIfNotFound, - ProcessorState* aPs, + txExecutionState& aEs, const NodeSet** aResult) { NS_ENSURE_TRUE(mKeyValues.mHashTable.ops && mIndexedKeys.mHashTable.ops, @@ -241,7 +241,7 @@ txKeyHash::getKeyNodes(const txExpandedName& aKeyName, return NS_ERROR_INVALID_ARG; } - nsresult rv = xslKey->indexDocument(aDocument, mKeyValues, aPs); + nsresult rv = xslKey->indexDocument(aDocument, mKeyValues, aEs); NS_ENSURE_SUCCESS(rv, rv); indexEntry->mIndexed = PR_TRUE; @@ -273,8 +273,6 @@ txXSLKey::~txXSLKey() txListIterator iter(&mKeys); Key* key; while ((key = (Key*)iter.next())) { - delete key->matchPattern; - delete key->useExpr; delete key; } } @@ -285,18 +283,22 @@ txXSLKey::~txXSLKey() * @param aUse use-expression * @return PR_FALSE if an error occured, PR_TRUE otherwise */ -PRBool txXSLKey::addKey(txPattern* aMatch, Expr* aUse) +PRBool txXSLKey::addKey(nsAutoPtr aMatch, nsAutoPtr aUse) { if (!aMatch || !aUse) return PR_FALSE; - Key* key = new Key; + nsAutoPtr key(new Key); if (!key) return PR_FALSE; key->matchPattern = aMatch; key->useExpr = aUse; - mKeys.add(key); + nsresult rv = mKeys.add(key); + NS_ENSURE_SUCCESS(rv, PR_FALSE); + + key.forget(); + return PR_TRUE; } @@ -304,14 +306,14 @@ PRBool txXSLKey::addKey(txPattern* aMatch, Expr* aUse) * Indexes a document and adds it to the hash of key values * @param aDocument Document to index and add * @param aKeyValueHash Hash to add values to - * @param aPs ProcessorState to use for XPath evaluation + * @param aEs txExecutionState to use for XPath evaluation */ nsresult txXSLKey::indexDocument(Document* aDocument, txKeyValueHash& aKeyValueHash, - ProcessorState* aPs) + txExecutionState& aEs) { txKeyValueHashKey key(mName, aDocument, NS_LITERAL_STRING("")); - return indexTree(aDocument, key, aKeyValueHash, aPs); + return indexTree(aDocument, key, aKeyValueHash, aEs); } /** @@ -320,27 +322,27 @@ nsresult txXSLKey::indexDocument(Document* aDocument, * @param aNode Node to search * @param aKey Key to use when adding into the hash * @param aKeyValueHash Hash to add values to - * @param aPs ProcessorState to use for XPath evaluation + * @param aEs txExecutionState to use for XPath evaluation */ nsresult txXSLKey::indexTree(Node* aNode, txKeyValueHashKey& aKey, txKeyValueHash& aKeyValueHash, - ProcessorState* aPs) + txExecutionState& aEs) { - nsresult rv = testNode(aNode, aKey, aKeyValueHash, aPs); + nsresult rv = testNode(aNode, aKey, aKeyValueHash, aEs); NS_ENSURE_SUCCESS(rv, rv); // check if the nodes attributes matches NamedNodeMap* attrs = aNode->getAttributes(); if (attrs) { for (PRUint32 i=0; igetLength(); i++) { - rv = testNode(attrs->item(i), aKey, aKeyValueHash, aPs); + rv = testNode(attrs->item(i), aKey, aKeyValueHash, aEs); NS_ENSURE_SUCCESS(rv, rv); } } Node* child = aNode->getFirstChild(); while (child) { - rv = indexTree(child, aKey, aKeyValueHash, aPs); + rv = indexTree(child, aKey, aKeyValueHash, aEs); NS_ENSURE_SUCCESS(rv, rv); child = child->getNextSibling(); @@ -355,22 +357,25 @@ nsresult txXSLKey::indexTree(Node* aNode, txKeyValueHashKey& aKey, * @param aNode Node to test * @param aKey Key to use when adding into the hash * @param aKeyValueHash Hash to add values to - * @param aPs ProcessorState to use for XPath evaluation + * @param aEs txExecutionState to use for XPath evaluation */ nsresult txXSLKey::testNode(Node* aNode, txKeyValueHashKey& aKey, - txKeyValueHash& aKeyValueHash, ProcessorState* aPs) + txKeyValueHash& aKeyValueHash, txExecutionState& aEs) { + nsresult rv = NS_OK; nsAutoString val; txListIterator iter(&mKeys); while (iter.hasNext()) { Key* key=(Key*)iter.next(); - if (key->matchPattern->matches(aNode, aPs)) { - txSingleNodeContext evalContext(aNode, aPs); - txIEvalContext* prevCon = - aPs->setEvalContext(&evalContext); + if (key->matchPattern->matches(aNode, &aEs)) { + txSingleNodeContext evalContext(aNode, &aEs); + rv = aEs.pushEvalContext(&evalContext); + NS_ENSURE_SUCCESS(rv, rv); + ExprResult* exprResult = key->useExpr->evaluate(&evalContext); - aPs->setEvalContext(prevCon); + aEs.popEvalContext(); + if (exprResult->getResultType() == ExprResult::NODESET) { NodeSet* res = (NodeSet*)exprResult; for (int i=0; isize(); i++) { diff --git a/mozilla/extensions/transformiix/source/xslt/txExecutionState.cpp b/mozilla/extensions/transformiix/source/xslt/txExecutionState.cpp new file mode 100644 index 00000000000..b5ce1bc5294 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/txExecutionState.cpp @@ -0,0 +1,635 @@ +/* -*- 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 + * Jonas Sicking. + * Portions created by the Initial Developer are Copyright (C) 2002 + * Jonas Sicking. All Rights Reserved. + * + * Contributor(s): + * Jonas Sicking + * + * 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 "txExecutionState.h" +#include "txSingleNodeContext.h" +#include "txInstructions.h" +#include "txStylesheet.h" +#include "txVariableMap.h" +#include "txRtfHandler.h" +#include "txXSLTProcessor.h" +#include "TxLog.h" +#include "txURIUtils.h" +#include "txXMLParser.h" + +#ifndef TX_EXE +#include "nsIDOMDocument.h" +#include "nsContentCID.h" +static NS_DEFINE_CID(kXMLDocumentCID, NS_XMLDOCUMENT_CID); +#endif + +const PRInt32 txExecutionState::kMaxRecursionDepth = 20000; + +DHASH_WRAPPER(txLoadedDocumentsBase, txLoadedDocumentEntry, nsAString&) + +nsresult txLoadedDocumentsHash::init(Document* aSourceDocument) +{ + nsresult rv = Init(8); + NS_ENSURE_SUCCESS(rv, rv); + + mSourceDocument = aSourceDocument; + Add(mSourceDocument); + + return NS_OK; +} + +txLoadedDocumentsHash::~txLoadedDocumentsHash() +{ + if (!mHashTable.ops) { + return; + } + + nsAutoString baseURI; + mSourceDocument->getBaseURI(baseURI); + txLoadedDocumentEntry* entry = GetEntry(baseURI); + if (entry) { + entry->mDocument = nsnull; + } +} + +void txLoadedDocumentsHash::Add(Document* aDocument) +{ + nsAutoString baseURI; + aDocument->getBaseURI(baseURI); + txLoadedDocumentEntry* entry = AddEntry(baseURI); + if (entry) { + entry->mDocument = aDocument; + } +} + +Document* txLoadedDocumentsHash::Get(const nsAString& aURI) +{ + txLoadedDocumentEntry* entry = GetEntry(aURI); + if (entry) { + return entry->mDocument; + } + + return nsnull; +} + +txExecutionState::txExecutionState(txStylesheet* aStylesheet) + : mTemplateParams(nsnull), + mStylesheet(aStylesheet), + mNextInstruction(nsnull), + mLocalVariables(nsnull), + mRecursionDepth(0), + mTemplateRules(nsnull), + mTemplateRulesBufferSize(0), + mTemplateRuleCount(0), + mEvalContext(nsnull), + mInitialEvalContext(nsnull), + mRTFDocument(nsnull), + mGlobalParams(nsnull), + mKeyHash(aStylesheet->getKeyMap()) +{ +} + +txExecutionState::~txExecutionState() +{ + delete mResultHandler; + delete mLocalVariables; + delete mEvalContext; + delete mRTFDocument; + delete mTemplateParams; + + PRInt32 i; + for (i = 0; i < mTemplateRuleCount; ++i) { + NS_IF_RELEASE(mTemplateRules[i].mModeLocalName); + } + delete [] mTemplateRules; + + txStackIterator varsIter(&mLocalVarsStack); + while (varsIter.hasNext()) { + delete (txVariableMap*)varsIter.next(); + } + + txStackIterator contextIter(&mEvalContextStack); + while (contextIter.hasNext()) { + txIEvalContext* context = (txIEvalContext*)contextIter.next(); + if (context != mInitialEvalContext) { + delete context; + } + } + + txStackIterator handlerIter(&mResultHandlerStack); + while (handlerIter.hasNext()) { + delete (txAXMLEventHandler*)handlerIter.next(); + } + + txStackIterator paramIter(&mParamStack); + while (paramIter.hasNext()) { + delete (txExpandedNameMap*)paramIter.next(); + } +} + +nsresult +txExecutionState::init(Node* aNode, + txExpandedNameMap* aGlobalParams) +{ + nsresult rv = NS_OK; + + mGlobalParams = aGlobalParams; + + // Set up initial context + mEvalContext = new txSingleNodeContext(aNode, this); + NS_ENSURE_TRUE(mEvalContext, NS_ERROR_OUT_OF_MEMORY); + + mInitialEvalContext = mEvalContext; + + // Set up output and result-handler + txAXMLEventHandler* handler = 0; + rv = mOutputHandlerFactory-> + createHandlerWith(mStylesheet->getOutputFormat(), &handler); + NS_ENSURE_SUCCESS(rv, rv); + + mOutputHandler = handler; + mResultHandler = handler; + mOutputHandler->startDocument(); + + // Initiate first instruction + txStylesheet::ImportFrame* frame = 0; + txExpandedName nullName; + txInstruction* templ = mStylesheet->findTemplate(aNode, nullName, + this, nsnull, &frame); + pushTemplateRule(frame, nullName, nsnull); + rv = runTemplate(templ); + NS_ENSURE_SUCCESS(rv, rv); + + // Set up loaded-documents-hash + Document* sourceDoc; + if (aNode->getNodeType() == Node::DOCUMENT_NODE) { + sourceDoc = (Document*)aNode; + } + else { + sourceDoc = aNode->getOwnerDocument(); + } + rv = mLoadedDocuments.init(sourceDoc); + NS_ENSURE_SUCCESS(rv, rv); + + // Init members + rv = mKeyHash.init(); + NS_ENSURE_SUCCESS(rv, rv); + + // The actual value here doesn't really matter since noone should use this + // value. But lets put something errorlike in just in case + mGlobalVarPlaceholderValue = new StringResult(NS_LITERAL_STRING("Error")); + NS_ENSURE_TRUE(mGlobalVarPlaceholderValue, NS_ERROR_OUT_OF_MEMORY); + + return NS_OK; +} + +nsresult +txExecutionState::end() +{ + popTemplateRule(); + mOutputHandler->endDocument(); + + return NS_OK; +} + + + +nsresult +txExecutionState::getVariable(PRInt32 aNamespace, nsIAtom* aLName, + ExprResult*& aResult) +{ + nsresult rv = NS_OK; + txExpandedName name(aNamespace, aLName); + + // look for a local variable + if (mLocalVariables) { + aResult = mLocalVariables->getVariable(name); + if (aResult) { + return NS_OK; + } + } + + // look for an evaluated global variable + aResult = mGlobalVariableValues.getVariable(name); + if (aResult) { + if (aResult == mGlobalVarPlaceholderValue) { + // XXX ErrorReport: cyclic variable-value + aResult = nsnull; + return NS_ERROR_XSLT_BAD_RECURSION; + } + return NS_OK; + } + + // Is there perchance a global variable not evaluated yet? + txStylesheet::GlobalVariable* var = mStylesheet->getGlobalVariable(name); + if (!var) { + // XXX ErrorReport: variable doesn't exist in this scope + return NS_ERROR_FAILURE; + } + + NS_ASSERTION(var->mExpr && !var->mFirstInstruction || + !var->mExpr && var->mFirstInstruction, + "global variable should have either instruction or expression"); + + // Is this a stylesheet parameter that has a value? + if (var->mIsParam && mGlobalParams) { + txIGlobalParameter* param = + (txIGlobalParameter*)mGlobalParams->get(name); + if (param) { + rv = param->getValue(&aResult); + NS_ENSURE_SUCCESS(rv, rv); + + rv = mGlobalVariableValues.bindVariable(name, aResult, PR_FALSE); + if (NS_FAILED(rv)) { + aResult = nsnull; + return rv; + } + + return NS_OK; + } + } + + // Insert a placeholdervalue to protect against recursion + rv = mGlobalVariableValues.bindVariable(name, mGlobalVarPlaceholderValue, + PR_FALSE); + NS_ENSURE_SUCCESS(rv, rv); + + // evaluate the global variable + pushEvalContext(mInitialEvalContext); + if (var->mExpr) { + txVariableMap* oldVars = mLocalVariables; + mLocalVariables = nsnull; + aResult = var->mExpr->evaluate(getEvalContext()); + NS_ENSURE_TRUE(aResult, NS_ERROR_FAILURE); + + mLocalVariables = oldVars; + } + else { + nsAutoPtr rtfHandler(new txRtfHandler); + NS_ENSURE_TRUE(rtfHandler, NS_ERROR_OUT_OF_MEMORY); + + rv = pushResultHandler(rtfHandler); + NS_ENSURE_SUCCESS(rv, rv); + + rtfHandler.forget(); + + txInstruction* prevInstr = mNextInstruction; + // set return to nsnull to stop execution + mNextInstruction = nsnull; + rv = runTemplate(var->mFirstInstruction); + NS_ENSURE_SUCCESS(rv, rv); + + rv = pushTemplateRule(nsnull, txExpandedName(), nsnull); + NS_ENSURE_SUCCESS(rv, rv); + + rv = txXSLTProcessor::execute(*this); + NS_ENSURE_SUCCESS(rv, rv); + + popTemplateRule(); + + mNextInstruction = prevInstr; + rtfHandler = (txRtfHandler*)popResultHandler(); + aResult = rtfHandler->createRTF(); + NS_ENSURE_TRUE(aResult, NS_ERROR_OUT_OF_MEMORY); + } + popEvalContext(); + + // Remove the placeholder and insert the calculated value + mGlobalVariableValues.removeVariable(name); + rv = mGlobalVariableValues.bindVariable(name, aResult, PR_TRUE); + if (NS_FAILED(rv)) { + delete aResult; + aResult = nsnull; + return rv; + } + + return NS_OK; +} + +PRBool +txExecutionState::isStripSpaceAllowed(Node* aNode) +{ + return mStylesheet->isStripSpaceAllowed(aNode, this); +} + +void* +txExecutionState::getPrivateContext() +{ + return this; +} + +void +txExecutionState::receiveError(const nsAString& aMsg, nsresult aRes) +{ + // XXX implement me +} + +nsresult +txExecutionState::pushEvalContext(txIEvalContext* aContext) +{ + nsresult rv = mEvalContextStack.push(mEvalContext); + NS_ENSURE_SUCCESS(rv, rv); + + mEvalContext = aContext; + + return NS_OK; +} + +txIEvalContext* +txExecutionState::popEvalContext() +{ + txIEvalContext* prev = mEvalContext; + mEvalContext = (txIEvalContext*)mEvalContextStack.pop(); + + return prev; +} + +nsresult +txExecutionState::pushString(const nsAString& aStr) +{ + if (!mStringStack.AppendString(aStr)) { + return NS_ERROR_OUT_OF_MEMORY; + } + + return NS_OK; +} + +void +txExecutionState::popString(nsAString& aStr) +{ + PRInt32 count = mStringStack.Count() - 1; + NS_ASSERTION(count >= 0, "stack is empty"); + mStringStack.StringAt(count, aStr); + mStringStack.RemoveStringAt(count); +} + +nsresult +txExecutionState::pushInt(PRInt32 aInt) +{ + return mIntStack.push(NS_INT32_TO_PTR(aInt)); +} + +PRInt32 +txExecutionState::popInt() +{ + return NS_PTR_TO_INT32(mIntStack.pop()); +} + +nsresult +txExecutionState::pushResultHandler(txAXMLEventHandler* aHandler) +{ + nsresult rv = mResultHandlerStack.push(mResultHandler); + NS_ENSURE_SUCCESS(rv, rv); + + mResultHandler = aHandler; + + return NS_OK; +} + +txAXMLEventHandler* +txExecutionState::popResultHandler() +{ + txAXMLEventHandler* oldHandler = mResultHandler; + mResultHandler = (txAXMLEventHandler*)mResultHandlerStack.pop(); + + return oldHandler; +} + +nsresult +txExecutionState::pushTemplateRule(txStylesheet::ImportFrame* aFrame, + const txExpandedName& aMode, + txExpandedNameMap* aParams) +{ + if (mTemplateRuleCount == mTemplateRulesBufferSize) { + PRInt32 newSize = + mTemplateRulesBufferSize ? mTemplateRulesBufferSize * 2 : 10; + TemplateRule* newRules = new TemplateRule[newSize]; + NS_ENSURE_TRUE(newRules, NS_ERROR_OUT_OF_MEMORY); + + memcpy(newRules, mTemplateRules, + mTemplateRuleCount * sizeof(TemplateRule)); + delete [] mTemplateRules; + mTemplateRules = newRules; + mTemplateRulesBufferSize = newSize; + } + + mTemplateRules[mTemplateRuleCount].mFrame = aFrame; + mTemplateRules[mTemplateRuleCount].mModeNsId = aMode.mNamespaceID; + mTemplateRules[mTemplateRuleCount].mModeLocalName = aMode.mLocalName; + mTemplateRules[mTemplateRuleCount].mParams = aParams; + NS_IF_ADDREF(mTemplateRules[mTemplateRuleCount].mModeLocalName); + ++mTemplateRuleCount; + + return NS_OK; +} + +void +txExecutionState::popTemplateRule() +{ + // decrement outside of RELEASE, that would decrement twice + --mTemplateRuleCount; + NS_IF_RELEASE(mTemplateRules[mTemplateRuleCount].mModeLocalName); +} + +txIEvalContext* +txExecutionState::getEvalContext() +{ + return mEvalContext; +} + +txExpandedNameMap* +txExecutionState::getParamMap() +{ + return mTemplateParams; +} + +Node* +txExecutionState::retrieveDocument(const nsAString& uri, + const nsAString& baseUri) +{ + nsAutoString absUrl; + URIUtils::resolveHref(uri, baseUri, absUrl); + + PRInt32 hash = absUrl.RFindChar(PRUnichar('#')); + PRUint32 urlEnd, fragStart, fragEnd; + if (hash == kNotFound) { + urlEnd = absUrl.Length(); + fragStart = 0; + fragEnd = 0; + } + else { + urlEnd = hash; + fragStart = hash + 1; + fragEnd = absUrl.Length(); + } + + nsDependentSubstring docUrl(absUrl, 0, urlEnd); + nsDependentSubstring frag(absUrl, fragStart, fragEnd); + + PR_LOG(txLog::xslt, PR_LOG_DEBUG, + ("Retrieve Document %s, uri %s, baseUri %s, fragment %s\n", + NS_LossyConvertUCS2toASCII(docUrl).get(), + NS_LossyConvertUCS2toASCII(uri).get(), + NS_LossyConvertUCS2toASCII(baseUri).get(), + NS_LossyConvertUCS2toASCII(frag).get())); + + // try to get already loaded document + Document* xmlDoc = mLoadedDocuments.Get(docUrl); + + if (!xmlDoc) { + // open URI + nsAutoString errMsg, refUri; + // XXX we should get the referrer from the actual node + // triggering the load, but this will do for the time being + mLoadedDocuments.mSourceDocument->getBaseURI(refUri); + nsresult rv; + rv = txParseDocumentFromURI(docUrl, refUri, + mLoadedDocuments.mSourceDocument, errMsg, + &xmlDoc); + + if (NS_FAILED(rv) || !xmlDoc) { + receiveError(NS_LITERAL_STRING("Couldn't load document '") + + docUrl + NS_LITERAL_STRING("': ") + errMsg, + NS_ERROR_XSLT_INVALID_URL); + return NULL; + } + // add to list of documents + mLoadedDocuments.Add(xmlDoc); + } + + // return element with supplied id if supplied + if (!frag.IsEmpty()) + return xmlDoc->getElementById(frag); + + return xmlDoc; +} + +nsresult +txExecutionState::getKeyNodes(const txExpandedName& aKeyName, + Document* aDocument, + const nsAString& aKeyValue, + PRBool aIndexIfNotFound, + const NodeSet** aResult) +{ + return mKeyHash.getKeyNodes(aKeyName, aDocument, aKeyValue, + aIndexIfNotFound, *this, aResult); +} + +txExecutionState::TemplateRule* +txExecutionState::getCurrentTemplateRule() +{ + return mTemplateRules + mTemplateRuleCount - 1; +} + +txInstruction* +txExecutionState::getNextInstruction() +{ + txInstruction* instr = mNextInstruction; + if (instr) { + mNextInstruction = instr->mNext; + } + + return instr; +} + +nsresult +txExecutionState::runTemplate(txInstruction* aTemplate) +{ + NS_ENSURE_TRUE(++mRecursionDepth < kMaxRecursionDepth, + NS_ERROR_XSLT_BAD_RECURSION); + + nsresult rv = mLocalVarsStack.push(mLocalVariables); + NS_ENSURE_SUCCESS(rv, rv); + + rv = mReturnStack.push(mNextInstruction); + NS_ENSURE_SUCCESS(rv, rv); + + mLocalVariables = nsnull; + mNextInstruction = aTemplate; + + return NS_OK; +} + +void +txExecutionState::gotoInstruction(txInstruction* aNext) +{ + mNextInstruction = aNext; +} + +void +txExecutionState::returnFromTemplate() +{ + --mRecursionDepth; + NS_ASSERTION(!mReturnStack.isEmpty() && !mLocalVarsStack.isEmpty(), + "return or variable stack is empty"); + delete mLocalVariables; + mNextInstruction = (txInstruction*)mReturnStack.pop(); + mLocalVariables = (txVariableMap*)mLocalVarsStack.pop(); +} + +nsresult +txExecutionState::bindVariable(const txExpandedName& aName, + ExprResult* aValue, MBool aOwned) +{ + if (!mLocalVariables) { + mLocalVariables = new txVariableMap; + NS_ENSURE_TRUE(mLocalVariables, NS_ERROR_OUT_OF_MEMORY); + } + return mLocalVariables->bindVariable(aName, aValue, aOwned); +} + +void +txExecutionState::removeVariable(const txExpandedName& aName) +{ + mLocalVariables->removeVariable(aName); +} + +nsresult +txExecutionState::pushParamMap(txExpandedNameMap* aParams) +{ + nsresult rv = mParamStack.push(mTemplateParams); + NS_ENSURE_SUCCESS(rv, rv); + + mTemplateParams = aParams; + + return NS_OK; +} + +txExpandedNameMap* +txExecutionState::popParamMap() +{ + txExpandedNameMap* oldParams = mTemplateParams; + mTemplateParams = (txExpandedNameMap*)mParamStack.pop(); + + return oldParams; +} diff --git a/mozilla/extensions/transformiix/source/xslt/txExecutionState.h b/mozilla/extensions/transformiix/source/xslt/txExecutionState.h new file mode 100644 index 00000000000..c6cdfe3159f --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/txExecutionState.h @@ -0,0 +1,182 @@ +/* -*- 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 + * Jonas Sicking. + * Portions created by the Initial Developer are Copyright (C) 2002 + * Jonas Sicking. All Rights Reserved. + * + * Contributor(s): + * Jonas Sicking + * + * 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_TXEXECUTIONSTATE_H +#define TRANSFRMX_TXEXECUTIONSTATE_H + +#include "txError.h" +#include "baseutils.h" +#include "txXMLEventHandler.h" +#include "nsCOMPtr.h" +#include "txStack.h" +#include "XMLUtils.h" +#include "nsVoidArray.h" +#include "txIXPathContext.h" +#include "txVariableMap.h" +#include "nsDoubleHashtable.h" +#include "txKey.h" +#include "txStylesheet.h" +#include "ExprResult.h" + +class txInstruction; +class txIOutputHandlerFactory; +class txExpandedNameMap; + + +class txLoadedDocumentEntry : public PLDHashStringEntry { +public: + txLoadedDocumentEntry(const void* aKey) : PLDHashStringEntry(aKey) + { + } + ~txLoadedDocumentEntry() + { + delete mDocument; + } + Document* mDocument; +}; + +DECL_DHASH_WRAPPER(txLoadedDocumentsBase, txLoadedDocumentEntry, nsAString&) + +class txLoadedDocumentsHash : public txLoadedDocumentsBase +{ +public: + ~txLoadedDocumentsHash(); + nsresult init(Document* aSourceDocument); + void Add(Document* aDocument); + Document* Get(const nsAString& aURI); + +private: + friend class txExecutionState; + Document* mSourceDocument; +}; + + +class txExecutionState : public txIMatchContext +{ +public: + txExecutionState(txStylesheet* aStylesheet); + ~txExecutionState(); + nsresult init(Node* aNode, txExpandedNameMap* aGlobalParams); + nsresult end(); + + TX_DECL_MATCH_CONTEXT; + + /** + * Struct holding information about a current template rule + */ + struct TemplateRule { + txStylesheet::ImportFrame* mFrame; + PRInt32 mModeNsId; + nsIAtom* mModeLocalName; + txExpandedNameMap* mParams; + }; + + // Stack functions + nsresult pushEvalContext(txIEvalContext* aContext); + txIEvalContext* popEvalContext(); + nsresult pushString(const nsAString& aStr); + void popString(nsAString& aStr); + nsresult pushInt(PRInt32 aInt); + PRInt32 popInt(); + nsresult pushResultHandler(txAXMLEventHandler* aHandler); + txAXMLEventHandler* popResultHandler(); + nsresult pushTemplateRule(txStylesheet::ImportFrame* aFrame, + const txExpandedName& aMode, + txExpandedNameMap* aParams); + void popTemplateRule(); + nsresult pushParamMap(txExpandedNameMap* aParams); + txExpandedNameMap* popParamMap(); + + // state-getting functions + txIEvalContext* getEvalContext(); + txExpandedNameMap* getParamMap(); + Node* retrieveDocument(const nsAString& uri, const nsAString& baseUri); + nsresult getKeyNodes(const txExpandedName& aKeyName, Document* aDocument, + const nsAString& aKeyValue, PRBool aIndexIfNotFound, + const NodeSet** aResult); + TemplateRule* getCurrentTemplateRule(); + + // state-modification functions + txInstruction* getNextInstruction(); + nsresult runTemplate(txInstruction* aInstruction); + nsresult runTemplate(txInstruction* aInstruction, + txInstruction* aReturnTo); + void gotoInstruction(txInstruction* aNext); + void returnFromTemplate(); + nsresult bindVariable(const txExpandedName& aName, + ExprResult* aValue, MBool aOwned); + void removeVariable(const txExpandedName& aName); + + txAXMLEventHandler* mOutputHandler; + txAXMLEventHandler* mResultHandler; + txAOutputHandlerFactory* mOutputHandlerFactory; + + txExpandedNameMap* mTemplateParams; + + nsRefPtr mStylesheet; + +private: + txStack mReturnStack; + txStack mLocalVarsStack; + txStack mEvalContextStack; + txStack mIntStack; + txStack mResultHandlerStack; + txStack mParamStack; + nsStringArray mStringStack; + txInstruction* mNextInstruction; + txVariableMap* mLocalVariables; + txVariableMap mGlobalVariableValues; + nsAutoPtr mGlobalVarPlaceholderValue; + PRInt32 mRecursionDepth; + + TemplateRule* mTemplateRules; + PRInt32 mTemplateRulesBufferSize; + PRInt32 mTemplateRuleCount; + + txIEvalContext* mEvalContext; + txIEvalContext* mInitialEvalContext; + Document* mRTFDocument; + txExpandedNameMap* mGlobalParams; + + txLoadedDocumentsHash mLoadedDocuments; + txKeyHash mKeyHash; + + static const PRInt32 kMaxRecursionDepth; +}; + +#endif diff --git a/mozilla/extensions/transformiix/source/xslt/txHTMLOutput.cpp b/mozilla/extensions/transformiix/source/xslt/txHTMLOutput.cpp index 0c6f1d7a8ce..ff9db5431c1 100644 --- a/mozilla/extensions/transformiix/source/xslt/txHTMLOutput.cpp +++ b/mozilla/extensions/transformiix/source/xslt/txHTMLOutput.cpp @@ -215,17 +215,17 @@ void txHTMLOutput::attribute(const nsAString& aName, if (shortHand && localPart.Equals(aValue, txCaseInsensitiveStringComparator())) { txListIterator iter(&mAttributes); - txAttribute* setAtt = 0; + txOutAttr* setAtt = 0; nsCOMPtr localName = do_GetAtom(localPart); txExpandedName att(aNsID, localName); - while ((setAtt = (txAttribute*)iter.next())) { + while ((setAtt = (txOutAttr*)iter.next())) { if (setAtt->mName == att) { setAtt->mShorthand = MB_TRUE; break; } } if (!setAtt) { - setAtt = new txAttribute(aNsID, localName, nsString()); + setAtt = new txOutAttr(aNsID, localName, nsString()); setAtt->mShorthand = MB_TRUE; mAttributes.add(setAtt); } diff --git a/mozilla/extensions/transformiix/source/xslt/txInstructions.cpp b/mozilla/extensions/transformiix/source/xslt/txInstructions.cpp new file mode 100644 index 00000000000..4b7d4b29942 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/txInstructions.cpp @@ -0,0 +1,1054 @@ +/* -*- 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 + * Jonas Sicking. + * Portions created by the Initial Developer are Copyright (C) 2002 + * Jonas Sicking. All Rights Reserved. + * + * Contributor(s): + * Jonas Sicking + * + * 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 "txInstructions.h" +#include "txError.h" +#include "Expr.h" +#include "ExprResult.h" +#include "txStylesheet.h" +#include "txNodeSetContext.h" +#include "txTextHandler.h" +#include "nsIConsoleService.h" +#include "nsIServiceManagerUtils.h" +#include "txStringUtils.h" +#include "txAtoms.h" +#include "txRtfHandler.h" +#include "txNodeSorter.h" +#include "txXSLTNumber.h" +#include "txExecutionState.h" + +nsresult +txApplyDefaultElementTemplate::execute(txExecutionState& aEs) +{ + txExecutionState::TemplateRule* rule = aEs.getCurrentTemplateRule(); + txExpandedName mode(rule->mModeNsId, rule->mModeLocalName); + txStylesheet::ImportFrame* frame = 0; + txInstruction* templ = + aEs.mStylesheet->findTemplate(aEs.getEvalContext()->getContextNode(), + mode, &aEs, nsnull, &frame); + + nsresult rv = aEs.pushTemplateRule(frame, mode, aEs.mTemplateParams); + NS_ENSURE_SUCCESS(rv, rv); + + return aEs.runTemplate(templ); +} + +nsresult +txApplyImportsEnd::execute(txExecutionState& aEs) +{ + aEs.popTemplateRule(); + aEs.popParamMap(); + + return NS_OK; +} + +nsresult +txApplyImportsStart::execute(txExecutionState& aEs) +{ + txExecutionState::TemplateRule* rule = aEs.getCurrentTemplateRule(); + // The frame is set to null when there is no current template rule, or + // when the current template rule is a default template. However this + // instruction isn't used in default templates. + if (!rule->mFrame) { + // XXX ErrorReport: apply-imports instantiated without a current rule + return NS_ERROR_XSLT_EXECUTION_FAILURE; + } + + nsresult rv = aEs.pushParamMap(rule->mParams); + NS_ENSURE_SUCCESS(rv, rv); + + txStylesheet::ImportFrame* frame = 0; + txExpandedName mode(rule->mModeNsId, rule->mModeLocalName); + txInstruction* templ = + aEs.mStylesheet->findTemplate(aEs.getEvalContext()->getContextNode(), + mode, &aEs, rule->mFrame, &frame); + + rv = aEs.pushTemplateRule(frame, mode, rule->mParams); + NS_ENSURE_SUCCESS(rv, rv); + + return aEs.runTemplate(templ); +} + +txApplyTemplates::txApplyTemplates(const txExpandedName& aMode) + : mMode(aMode) +{ +} + +nsresult +txApplyTemplates::execute(txExecutionState& aEs) +{ + txStylesheet::ImportFrame* frame = 0; + txInstruction* templ = + aEs.mStylesheet->findTemplate(aEs.getEvalContext()->getContextNode(), + mMode, &aEs, nsnull, &frame); + + nsresult rv = aEs.pushTemplateRule(frame, mMode, aEs.mTemplateParams); + NS_ENSURE_SUCCESS(rv, rv); + + return aEs.runTemplate(templ); +} + +txAttribute::txAttribute(nsAutoPtr aName, nsAutoPtr aNamespace, + txNamespaceMap* aMappings) + : mName(aName), + mNamespace(aNamespace), + mMappings(aMappings) +{ +} + +nsresult +txAttribute::execute(txExecutionState& aEs) +{ + nsresult rv = NS_OK; + + ExprResult* exprRes = mName->evaluate(aEs.getEvalContext()); + NS_ENSURE_TRUE(exprRes, NS_ERROR_FAILURE); + + nsAutoString name; + exprRes->stringValue(name); + delete exprRes; + + if (!XMLUtils::isValidQName(name) || + TX_StringEqualsAtom(name, txXMLAtoms::xmlns)) { + // truncate name to indicate failure + name.Truncate(); + } + + nsCOMPtr prefix; + XMLUtils::getPrefix(name, getter_AddRefs(prefix)); + + PRInt32 nsId = kNameSpaceID_None; + if (!name.IsEmpty()) { + if (mNamespace) { + exprRes = mNamespace->evaluate(aEs.getEvalContext()); + NS_ENSURE_TRUE(exprRes, NS_ERROR_FAILURE); + + nsAutoString nspace; + exprRes->stringValue(nspace); + delete exprRes; + + if (!nspace.IsEmpty()) { +#ifdef TX_EXE + nsId = txNamespaceManager::getNamespaceID(nspace); +#else + NS_ASSERTION(gTxNameSpaceManager, "No namespace manager"); + rv = gTxNameSpaceManager->RegisterNameSpace(nspace, nsId); + NS_ENSURE_SUCCESS(rv, rv); +#endif + } + } + else if (prefix) { + nsId = mMappings->lookupNamespace(prefix); + if (nsId == kNameSpaceID_Unknown) { + // tunkate name to indicate failure + name.Truncate(); + } + } + } + + if (prefix == txXMLAtoms::xmlns) { + // Cut xmlns: (6 characters) + name.Cut(0, 6); + } + + txTextHandler* handler = + NS_STATIC_CAST(txTextHandler*, aEs.popResultHandler()); + if (!name.IsEmpty()) { + // add attribute if everything was ok + aEs.mResultHandler->attribute(name, nsId, handler->mValue); + } + delete handler; + + return NS_OK; +} + +txCallTemplate::txCallTemplate(const txExpandedName& aName) + : mName(aName) +{ +} + +nsresult +txCallTemplate::execute(txExecutionState& aEs) +{ + txInstruction* instr = aEs.mStylesheet->getNamedTemplate(mName); + NS_ENSURE_TRUE(instr, NS_ERROR_XSLT_EXECUTION_FAILURE); + + nsresult rv = aEs.runTemplate(instr); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + +txCheckParam::txCheckParam(const txExpandedName& aName) + : mName(aName), mBailTarget(nsnull) +{ +} + +nsresult +txCheckParam::execute(txExecutionState& aEs) +{ + nsresult rv = NS_OK; + if (aEs.mTemplateParams) { + ExprResult* exprRes = + NS_STATIC_CAST(ExprResult*, aEs.mTemplateParams->get(mName)); + if (exprRes) { + rv = aEs.bindVariable(mName, exprRes, MB_FALSE); + NS_ENSURE_SUCCESS(rv, rv); + + aEs.gotoInstruction(mBailTarget); + } + } + + return NS_OK; +} + +txConditionalGoto::txConditionalGoto(nsAutoPtr aCondition, + txInstruction* aTarget) + : mCondition(aCondition), + mTarget(aTarget) +{ +} + +nsresult +txConditionalGoto::execute(txExecutionState& aEs) +{ + ExprResult* exprRes = mCondition->evaluate(aEs.getEvalContext()); + NS_ENSURE_TRUE(exprRes, NS_ERROR_FAILURE); + + if (!exprRes->booleanValue()) { + aEs.gotoInstruction(mTarget); + } + delete exprRes; + + return NS_OK; +} + +nsresult +txComment::execute(txExecutionState& aEs) +{ + txTextHandler* handler = + NS_STATIC_CAST(txTextHandler*, aEs.popResultHandler()); + PRUint32 length = handler->mValue.Length(); + PRInt32 pos = 0; + while ((pos = handler->mValue.FindChar('-', (PRUint32)pos)) != kNotFound) { + ++pos; + if ((PRUint32)pos == length || handler->mValue.CharAt(pos) == '-') { + handler->mValue.Insert(PRUnichar(' '), pos++); + ++length; + } + } + + aEs.mResultHandler->comment(handler->mValue); + delete handler; + + return NS_OK; +} + +nsresult +txCopyBase::copyNode(Node* aNode, txExecutionState& aEs) +{ + NS_ASSERTION(aNode, "missing node to copy"); + switch (aNode->getNodeType()) { + case Node::ATTRIBUTE_NODE: + { + nsAutoString nodeName, nodeValue; + aNode->getNodeName(nodeName); + aNode->getNodeValue(nodeValue); + aEs.mResultHandler->attribute(nodeName, + aNode->getNamespaceID(), + nodeValue); + break; + } + case Node::COMMENT_NODE: + { + nsAutoString nodeValue; + aNode->getNodeValue(nodeValue); + aEs.mResultHandler->comment(nodeValue); + break; + } + case Node::DOCUMENT_NODE: + case Node::DOCUMENT_FRAGMENT_NODE: + { + // Copy children + Node* child = aNode->getFirstChild(); + while (child) { + copyNode(child, aEs); + child = child->getNextSibling(); + } + break; + } + case Node::ELEMENT_NODE: + { + Element* element = NS_STATIC_CAST(Element*, aNode); + nsAutoString name; + element->getNodeName(name); + PRInt32 nsID = element->getNamespaceID(); + aEs.mResultHandler->startElement(name, nsID); + + // Copy attributes + NamedNodeMap* attList = element->getAttributes(); + if (attList) { + PRUint32 i = 0; + for (i = 0; i < attList->getLength(); i++) { + Attr* attr = NS_STATIC_CAST(Attr*, attList->item(i)); + nsAutoString nodeName, nodeValue; + attr->getNodeName(nodeName); + attr->getNodeValue(nodeValue); + aEs.mResultHandler->attribute(nodeName, + attr->getNamespaceID(), + nodeValue); + } + } + + // Copy children + Node* child = element->getFirstChild(); + while (child) { + copyNode(child, aEs); + child = child->getNextSibling(); + } + + aEs.mResultHandler->endElement(name, nsID); + break; + } + case Node::PROCESSING_INSTRUCTION_NODE: + { + nsAutoString target, data; + aNode->getNodeName(target); + aNode->getNodeValue(data); + aEs.mResultHandler->processingInstruction(target, data); + break; + } + case Node::TEXT_NODE: + case Node::CDATA_SECTION_NODE: + { + nsAutoString nodeValue; + aNode->getNodeValue(nodeValue); + aEs.mResultHandler->characters(nodeValue, PR_FALSE); + break; + } + } + + return NS_OK; +} + +txCopy::txCopy() + : mBailTarget(nsnull) +{ +} + +nsresult +txCopy::execute(txExecutionState& aEs) +{ + nsresult rv = NS_OK; + Node* node = aEs.getEvalContext()->getContextNode(); + + switch (node->getNodeType()) { + case Node::DOCUMENT_NODE: + { + // "close" current element to ensure that no attributes are added + aEs.mResultHandler->characters(NS_LITERAL_STRING(""), PR_FALSE); + + rv = aEs.pushString(NS_LITERAL_STRING("")); + NS_ENSURE_SUCCESS(rv, rv); + + rv = aEs.pushInt(kNameSpaceID_None); + NS_ENSURE_SUCCESS(rv, rv); + + break; + } + case Node::ELEMENT_NODE: + { + nsAutoString nodeName; + node->getNodeName(nodeName); + PRInt32 nsID = node->getNamespaceID(); + + aEs.mResultHandler->startElement(nodeName, nsID); + // XXX copy namespace nodes once we have them + + rv = aEs.pushString(nodeName); + NS_ENSURE_SUCCESS(rv, rv); + + rv = aEs.pushInt(nsID); + NS_ENSURE_SUCCESS(rv, rv); + + break; + } + default: + { + rv = copyNode(node, aEs); + NS_ENSURE_SUCCESS(rv, rv); + + aEs.gotoInstruction(mBailTarget); + } + } + + return NS_OK; +} + +txCopyOf::txCopyOf(nsAutoPtr aSelect) + : mSelect(aSelect) +{ +} + +nsresult +txCopyOf::execute(txExecutionState& aEs) +{ + nsresult rv = NS_OK; + ExprResult* exprRes = mSelect->evaluate(aEs.getEvalContext()); + NS_ENSURE_TRUE(exprRes, NS_ERROR_FAILURE); + + switch (exprRes->getResultType()) { + case ExprResult::NODESET: + { + NodeSet* nodes = NS_STATIC_CAST(NodeSet*, exprRes); + int i; + for (i = 0; i < nodes->size(); ++i) { + Node* node = nodes->get(i); + rv = copyNode(node, aEs); + if (NS_FAILED(rv)) { + delete exprRes; + return rv; + } + } + break; + } + case ExprResult::RESULT_TREE_FRAGMENT: + { + txResultTreeFragment* rtf = NS_STATIC_CAST(txResultTreeFragment*, + exprRes); + rv = rtf->flushToHandler(aEs.mResultHandler); + if (NS_FAILED(rv)) { + delete exprRes; + return rv; + } + break; + } + default: + { + nsAutoString value; + exprRes->stringValue(value); + if (!value.IsEmpty()) { + aEs.mResultHandler->characters(value, PR_FALSE); + } + break; + } + } + + delete exprRes; + + return NS_OK; +} + +nsresult +txEndElement::execute(txExecutionState& aEs) +{ + PRInt32 namespaceID = aEs.popInt(); + nsAutoString nodeName; + aEs.popString(nodeName); + + + // For xsl:elements with a bad name we push an empty name + if (!nodeName.IsEmpty()) { + aEs.mResultHandler->endElement(nodeName, namespaceID); + } + + return NS_OK; +} + +nsresult +txErrorInstruction::execute(txExecutionState& aEs) +{ + // XXX ErrorReport: unknown instruction executed + return NS_ERROR_XSLT_EXECUTION_FAILURE; +} + +txGoTo::txGoTo(txInstruction* aTarget) + : mTarget(aTarget) +{ +} + +nsresult +txGoTo::execute(txExecutionState& aEs) +{ + aEs.gotoInstruction(mTarget); + + return NS_OK; +} + +txInsertAttrSet::txInsertAttrSet(const txExpandedName& aName) + : mName(aName) +{ +} + +nsresult +txInsertAttrSet::execute(txExecutionState& aEs) +{ + txInstruction* instr = aEs.mStylesheet->getAttributeSet(mName); + NS_ENSURE_TRUE(instr, NS_ERROR_XSLT_EXECUTION_FAILURE); + + nsresult rv = aEs.runTemplate(instr); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + +txLoopNodeSet::txLoopNodeSet(txInstruction* aTarget) + : mTarget(aTarget) +{ +} + +nsresult +txLoopNodeSet::execute(txExecutionState& aEs) +{ + aEs.popTemplateRule(); + txNodeSetContext* context = + NS_STATIC_CAST(txNodeSetContext*, aEs.getEvalContext()); + if (!context->hasNext()) { + delete aEs.popEvalContext(); + + return NS_OK; + } + + context->next(); + aEs.gotoInstruction(mTarget); + + return NS_OK; +} + +txLREAttribute::txLREAttribute(PRInt32 aNamespaceID, nsIAtom* aLocalName, + nsIAtom* aPrefix, nsAutoPtr aValue) + : mNamespaceID(aNamespaceID), + mLocalName(aLocalName), + mPrefix(aPrefix), + mValue(aValue) +{ +} + +nsresult +txLREAttribute::execute(txExecutionState& aEs) +{ + // We should atomize the resulthandler + nsAutoString nodeName; + if (mPrefix) { + mPrefix->ToString(nodeName); + nsAutoString localName; + nodeName.Append(PRUnichar(':')); + mLocalName->ToString(localName); + nodeName.Append(localName); + } + else { + mLocalName->ToString(nodeName); + } + + ExprResult* exprRes = mValue->evaluate(aEs.getEvalContext()); + NS_ENSURE_TRUE(exprRes, NS_ERROR_FAILURE); + + nsAutoString value; + exprRes->stringValue(value); + delete exprRes; + + aEs.mResultHandler->attribute(nodeName, mNamespaceID, value); + + return NS_OK; +} + +txMessage::txMessage(PRBool aTerminate) + : mTerminate(aTerminate) +{ +} + +nsresult +txMessage::execute(txExecutionState& aEs) +{ + txTextHandler* handler = + NS_STATIC_CAST(txTextHandler*, aEs.popResultHandler()); + + nsCOMPtr consoleSvc = + do_GetService("@mozilla.org/consoleservice;1"); + if (consoleSvc) { + nsAutoString logString(NS_LITERAL_STRING("xsl:message - ")); + logString.Append(handler->mValue); + consoleSvc->LogStringMessage(logString.get()); + } + delete handler; + + return mTerminate ? NS_ERROR_XSLT_ABORTED : NS_OK; +} + +txNumber::txNumber(txXSLTNumber::LevelType aLevel, nsAutoPtr aCount, + nsAutoPtr aFrom, nsAutoPtr aValue, + nsAutoPtr aFormat, nsAutoPtr aGroupingSeparator, + nsAutoPtr aGroupingSize) + : mLevel(aLevel), mCount(aCount), mFrom(aFrom), mValue(aValue), + mFormat(aFormat), mGroupingSeparator(aGroupingSeparator), + mGroupingSize(aGroupingSize) +{ +} + +nsresult +txNumber::execute(txExecutionState& aEs) +{ + nsAutoString res; + nsresult rv = + txXSLTNumber::createNumber(mValue, mCount, mFrom, mLevel, mGroupingSize, + mGroupingSeparator, mFormat, + aEs.getEvalContext(), res); + NS_ENSURE_SUCCESS(rv, rv); + + aEs.mResultHandler->characters(res, PR_FALSE); + + return NS_OK; +} + +nsresult +txPopParams::execute(txExecutionState& aEs) +{ + delete aEs.popParamMap(); + + return NS_OK; +} + +txProcessingInstruction::txProcessingInstruction(nsAutoPtr aName) + : mName(aName) +{ +} + +nsresult +txProcessingInstruction::execute(txExecutionState& aEs) +{ + txTextHandler* handler = + NS_STATIC_CAST(txTextHandler*, aEs.popResultHandler()); + XMLUtils::normalizePIValue(handler->mValue); + + ExprResult* exprRes = mName->evaluate(aEs.getEvalContext()); + NS_ENSURE_TRUE(exprRes, NS_ERROR_FAILURE); + + nsAutoString name; + exprRes->stringValue(name); + delete exprRes; + + // Check name validity (must be valid NCName and a PITarget) + // XXX Need to check for NCName and PITarget + if (!XMLUtils::isValidQName(name)) { + // XXX ErrorReport: bad PI-target + delete handler; + return NS_ERROR_FAILURE; + } + + aEs.mResultHandler->processingInstruction(name, handler->mValue); + + return NS_OK; +} + +txPushNewContext::txPushNewContext(nsAutoPtr aSelect) + : mSelect(aSelect), mBailTarget(nsnull) +{ +} + +txPushNewContext::~txPushNewContext() +{ + PRInt32 i; + for (i = 0; i < mSortKeys.Count(); ++i) + { + delete NS_STATIC_CAST(SortKey*, mSortKeys[i]); + } +} + +nsresult +txPushNewContext::execute(txExecutionState& aEs) +{ + nsresult rv = NS_OK; + ExprResult* exprRes = mSelect->evaluate(aEs.getEvalContext()); + NS_ENSURE_TRUE(exprRes, NS_ERROR_FAILURE); + + if (exprRes->getResultType() != ExprResult::NODESET) { + delete exprRes; + // XXX ErrorReport: nodeset expected + return NS_ERROR_XSLT_NODESET_EXPECTED; + } + + NodeSet* nodes = NS_STATIC_CAST(NodeSet*, exprRes); + + if (nodes->isEmpty()) { + aEs.gotoInstruction(mBailTarget); + + return NS_OK; + } + + txNodeSorter sorter; + PRInt32 i, count = mSortKeys.Count(); + for (i = 0; i < count; ++i) { + SortKey* sort = NS_STATIC_CAST(SortKey*, mSortKeys[i]); + rv = sorter.addSortElement(sort->mSelectExpr, sort->mLangExpr, + sort->mDataTypeExpr, sort->mOrderExpr, + sort->mCaseOrderExpr, + aEs.getEvalContext()); + NS_ENSURE_SUCCESS(rv, rv); + } + rv = sorter.sortNodeSet(nodes, &aEs); + NS_ENSURE_SUCCESS(rv, rv); + + txNodeSetContext* context = new txOwningNodeSetContext(nodes, &aEs); + if (!context) { + delete exprRes; + return NS_ERROR_OUT_OF_MEMORY; + } + + context->next(); + + rv = aEs.pushEvalContext(context); + if (NS_FAILED(rv)) { + delete context; + return rv; + } + + return NS_OK; +} + +nsresult +txPushNewContext::addSort(nsAutoPtr aSelectExpr, + nsAutoPtr aLangExpr, + nsAutoPtr aDataTypeExpr, + nsAutoPtr aOrderExpr, + nsAutoPtr aCaseOrderExpr) +{ + SortKey* sort = new SortKey(aSelectExpr, aLangExpr, aDataTypeExpr, + aOrderExpr, aCaseOrderExpr); + NS_ENSURE_TRUE(sort, NS_ERROR_OUT_OF_MEMORY); + + if (!mSortKeys.AppendElement(sort)) { + delete sort; + return NS_ERROR_OUT_OF_MEMORY; + } + + return NS_OK; +} + +txPushNewContext::SortKey::SortKey(nsAutoPtr aSelectExpr, + nsAutoPtr aLangExpr, + nsAutoPtr aDataTypeExpr, + nsAutoPtr aOrderExpr, + nsAutoPtr aCaseOrderExpr) + : mSelectExpr(aSelectExpr), mLangExpr(aLangExpr), + mDataTypeExpr(aDataTypeExpr), mOrderExpr(aOrderExpr), + mCaseOrderExpr(aCaseOrderExpr) +{ +} + +nsresult +txPushNullTemplateRule::execute(txExecutionState& aEs) +{ + return aEs.pushTemplateRule(nsnull, txExpandedName(), nsnull); +} + +nsresult +txPushParams::execute(txExecutionState& aEs) +{ + return aEs.pushParamMap(nsnull); +} + +nsresult +txPushRTFHandler::execute(txExecutionState& aEs) +{ + txAXMLEventHandler* handler = new txRtfHandler; + NS_ENSURE_TRUE(handler, NS_ERROR_OUT_OF_MEMORY); + + nsresult rv = aEs.pushResultHandler(handler); + if (NS_FAILED(rv)) { + delete handler; + return rv; + } + + return NS_OK; +} + +txPushStringHandler::txPushStringHandler(PRBool aOnlyText) + : mOnlyText(aOnlyText) +{ +} + +nsresult +txPushStringHandler::execute(txExecutionState& aEs) +{ + txAXMLEventHandler* handler = new txTextHandler(mOnlyText); + NS_ENSURE_TRUE(handler, NS_ERROR_OUT_OF_MEMORY); + + nsresult rv = aEs.pushResultHandler(handler); + if (NS_FAILED(rv)) { + delete handler; + return rv; + } + + return NS_OK; +} + +txRemoveVariable::txRemoveVariable(const txExpandedName& aName) + : mName(aName) +{ +} + +nsresult +txRemoveVariable::execute(txExecutionState& aEs) +{ + aEs.removeVariable(mName); + + return NS_OK; +} + +nsresult +txReturn::execute(txExecutionState& aEs) +{ + NS_ASSERTION(!mNext, "instructions exist after txReturn"); + aEs.returnFromTemplate(); + + return NS_OK; +} + +txSetParam::txSetParam(const txExpandedName& aName, nsAutoPtr aValue) + : mName(aName), mValue(aValue) +{ +} + +nsresult +txSetParam::execute(txExecutionState& aEs) +{ + if (!aEs.mTemplateParams) { + aEs.mTemplateParams = new txExpandedNameMap(PR_TRUE); + NS_ENSURE_TRUE(aEs.mTemplateParams, NS_ERROR_OUT_OF_MEMORY); + } + + ExprResult* exprRes; + if (mValue) { + exprRes = mValue->evaluate(aEs.getEvalContext()); + NS_ENSURE_TRUE(exprRes, NS_ERROR_FAILURE); + } + else { + txRtfHandler* rtfHandler = + NS_STATIC_CAST(txRtfHandler*, aEs.popResultHandler()); + exprRes = rtfHandler->createRTF(); + delete rtfHandler; + NS_ENSURE_TRUE(exprRes, NS_ERROR_OUT_OF_MEMORY); + } + + nsresult rv = aEs.mTemplateParams->add(mName, exprRes); + if (NS_FAILED(rv)) { + delete exprRes; + return rv; + } + + return NS_OK; +} + +txSetVariable::txSetVariable(const txExpandedName& aName, + nsAutoPtr aValue) + : mName(aName), mValue(aValue) +{ +} + +nsresult +txSetVariable::execute(txExecutionState& aEs) +{ + ExprResult* exprRes; + if (mValue) { + exprRes = mValue->evaluate(aEs.getEvalContext()); + NS_ENSURE_TRUE(exprRes, NS_ERROR_FAILURE); + } + else { + txRtfHandler* rtfHandler = + NS_STATIC_CAST(txRtfHandler*, aEs.popResultHandler()); + exprRes = rtfHandler->createRTF(); + delete rtfHandler; + NS_ENSURE_TRUE(exprRes, NS_ERROR_OUT_OF_MEMORY); + } + + nsresult rv = aEs.bindVariable(mName, exprRes, MB_TRUE); + if (NS_FAILED(rv)) { + delete exprRes; + return rv; + } + + return NS_OK; +} + +txStartElement::txStartElement(nsAutoPtr aName, + nsAutoPtr aNamespace, + txNamespaceMap* aMappings) + : mName(aName), + mNamespace(aNamespace), + mMappings(aMappings) +{ +} + +nsresult +txStartElement::execute(txExecutionState& aEs) +{ + nsresult rv = NS_OK; + + ExprResult* exprRes = mName->evaluate(aEs.getEvalContext()); + NS_ENSURE_TRUE(exprRes, NS_ERROR_FAILURE); + + nsAutoString name; + exprRes->stringValue(name); + delete exprRes; + + if (!XMLUtils::isValidQName(name)) { + // tunkate name to indicate failure + name.Truncate(); + } + + PRInt32 nsId = kNameSpaceID_None; + if (!name.IsEmpty()) { + if (mNamespace) { + exprRes = mNamespace->evaluate(aEs.getEvalContext()); + NS_ENSURE_TRUE(exprRes, NS_ERROR_FAILURE); + + nsAutoString nspace; + exprRes->stringValue(nspace); + delete exprRes; + + if (!nspace.IsEmpty()) { +#ifdef TX_EXE + nsId = txNamespaceManager::getNamespaceID(nspace); +#else + NS_ASSERTION(gTxNameSpaceManager, "No namespace manager"); + rv = gTxNameSpaceManager->RegisterNameSpace(nspace, nsId); + NS_ENSURE_SUCCESS(rv, rv); +#endif + } + } + else { + nsCOMPtr prefix; + XMLUtils::getPrefix(name, getter_AddRefs(prefix)); + nsId = mMappings->lookupNamespace(prefix); + if (nsId == kNameSpaceID_Unknown) { + // tunkate name to indicate failure + name.Truncate(); + } + } + } + + if (!name.IsEmpty()) { + // add element if everything was ok + aEs.mResultHandler->startElement(name, nsId); + } + else { + // we call characters with an empty string to "close" any element to + // make sure that no attributes are added + aEs.mResultHandler->characters(nsString(), PR_FALSE); + } + + rv = aEs.pushString(name); + NS_ENSURE_SUCCESS(rv, rv); + + rv = aEs.pushInt(nsId); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + + +txStartLREElement::txStartLREElement(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix) + : mNamespaceID(aNamespaceID), + mLocalName(aLocalName), + mPrefix(aPrefix) +{ +} + +nsresult +txStartLREElement::execute(txExecutionState& aEs) +{ + // We should atomize the resulthandler + nsAutoString nodeName; + if (mPrefix) { + mPrefix->ToString(nodeName); + nsAutoString localName; + nodeName.Append(PRUnichar(':')); + mLocalName->ToString(localName); + nodeName.Append(localName); + } + else { + mLocalName->ToString(nodeName); + } + + aEs.mResultHandler->startElement(nodeName, mNamespaceID); + + nsresult rv = aEs.pushString(nodeName); + NS_ENSURE_SUCCESS(rv, rv); + + rv = aEs.pushInt(mNamespaceID); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + +txText::txText(const nsAString& aStr, PRBool aDOE) + : mStr(aStr), + mDOE(aDOE) +{ +} + +nsresult +txText::execute(txExecutionState& aEs) +{ + aEs.mResultHandler->characters(mStr, mDOE); + return NS_OK; +} + +txValueOf::txValueOf(nsAutoPtr aExpr, PRBool aDOE) + : mExpr(aExpr), + mDOE(aDOE) +{ +} + +nsresult +txValueOf::execute(txExecutionState& aEs) +{ + ExprResult* exprRes = mExpr->evaluate(aEs.getEvalContext()); + NS_ENSURE_TRUE(exprRes, NS_ERROR_FAILURE); + + nsAutoString value; + exprRes->stringValue(value); + delete exprRes; + + if (!value.IsEmpty()) { + aEs.mResultHandler->characters(value, mDOE); + } + return NS_OK; +} diff --git a/mozilla/extensions/transformiix/source/xslt/txInstructions.h b/mozilla/extensions/transformiix/source/xslt/txInstructions.h new file mode 100644 index 00000000000..b8bef705a1c --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/txInstructions.h @@ -0,0 +1,427 @@ +/* -*- 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 + * Jonas Sicking. + * Portions created by the Initial Developer are Copyright (C) 2002 + * Jonas Sicking. All Rights Reserved. + * + * Contributor(s): + * Jonas Sicking + * + * 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_TXINSTRUCTIONS_H +#define TRANSFRMX_TXINSTRUCTIONS_H + +#include "txError.h" +#include "nsCOMPtr.h" +#include "TxObject.h" +#include "nsIAtom.h" +#include "nsString.h" +#include "XMLUtils.h" +#include "txNamespaceMap.h" +#include "nsAutoPtr.h" +#include "Expr.h" +#include "txXSLTNumber.h" +#include "txXSLTPatterns.h" + +class txExecutionState; + +class txInstruction : public TxObject +{ +public: + txInstruction() : mNext(0) + { + } + + virtual ~txInstruction() + { + delete mNext; + } + + virtual nsresult execute(txExecutionState& aEs) = 0; + + txInstruction* mNext; +}; + +#define TX_DECL_TXINSTRUCTION \ + virtual nsresult execute(txExecutionState& aEs); + + +class txApplyDefaultElementTemplate : public txInstruction +{ +public: + TX_DECL_TXINSTRUCTION +}; + +class txApplyImportsEnd : public txInstruction +{ +public: + TX_DECL_TXINSTRUCTION +}; + +class txApplyImportsStart : public txInstruction +{ +public: + TX_DECL_TXINSTRUCTION +}; + +class txApplyTemplates : public txInstruction +{ +public: + txApplyTemplates(const txExpandedName& aMode); + + TX_DECL_TXINSTRUCTION + + txExpandedName mMode; +}; + +class txAttribute : public txInstruction +{ +public: + txAttribute(nsAutoPtr aName, nsAutoPtr aNamespace, + txNamespaceMap* aMappings); + + TX_DECL_TXINSTRUCTION + + nsAutoPtr mName; + nsAutoPtr mNamespace; + nsRefPtr mMappings; +}; + +class txCallTemplate : public txInstruction +{ +public: + txCallTemplate(const txExpandedName& aName); + + TX_DECL_TXINSTRUCTION + + txExpandedName mName; +}; + +class txCheckParam : public txInstruction +{ +public: + txCheckParam(const txExpandedName& aName); + + TX_DECL_TXINSTRUCTION + + txExpandedName mName; + txInstruction* mBailTarget; +}; + +class txConditionalGoto : public txInstruction +{ +public: + txConditionalGoto(nsAutoPtr aCondition, txInstruction* aTarget); + + TX_DECL_TXINSTRUCTION + + nsAutoPtr mCondition; + txInstruction* mTarget; +}; + +class txComment : public txInstruction +{ +public: + TX_DECL_TXINSTRUCTION +}; + +class txCopyBase : public txInstruction +{ +protected: + nsresult copyNode(Node* aNode, txExecutionState& aEs); +}; + +class txCopy : public txCopyBase +{ +public: + txCopy(); + + TX_DECL_TXINSTRUCTION + + txInstruction* mBailTarget; +}; + +class txCopyOf : public txCopyBase +{ +public: + txCopyOf(nsAutoPtr aSelect); + + TX_DECL_TXINSTRUCTION + + nsAutoPtr mSelect; +}; + +class txEndElement : public txInstruction +{ +public: + TX_DECL_TXINSTRUCTION +}; + +class txErrorInstruction : public txInstruction +{ +public: + TX_DECL_TXINSTRUCTION +}; + +class txGoTo : public txInstruction +{ +public: + txGoTo(txInstruction* aTarget); + + TX_DECL_TXINSTRUCTION + + txInstruction* mTarget; +}; + +class txInsertAttrSet : public txInstruction +{ +public: + txInsertAttrSet(const txExpandedName& aName); + + TX_DECL_TXINSTRUCTION + + txExpandedName mName; +}; + +class txLoopNodeSet : public txInstruction +{ +public: + txLoopNodeSet(txInstruction* aTarget); + + TX_DECL_TXINSTRUCTION + + txInstruction* mTarget; +}; + +class txLREAttribute : public txInstruction +{ +public: + txLREAttribute(PRInt32 aNamespaceID, nsIAtom* aLocalName, + nsIAtom* aPrefix, nsAutoPtr aValue); + + TX_DECL_TXINSTRUCTION + + PRInt32 mNamespaceID; + nsCOMPtr mLocalName; + nsCOMPtr mPrefix; + nsAutoPtr mValue; +}; + +class txMessage : public txInstruction +{ +public: + txMessage(PRBool aTerminate); + + TX_DECL_TXINSTRUCTION + + PRBool mTerminate; +}; + +class txNumber : public txInstruction +{ +public: + txNumber(txXSLTNumber::LevelType aLevel, nsAutoPtr aCount, + nsAutoPtr aFrom, nsAutoPtr aValue, + nsAutoPtr aFormat, nsAutoPtr aGroupingSeparator, + nsAutoPtr aGroupingSize); + + TX_DECL_TXINSTRUCTION + + txXSLTNumber::LevelType mLevel; + nsAutoPtr mCount; + nsAutoPtr mFrom; + nsAutoPtr mValue; + nsAutoPtr mFormat; + nsAutoPtr mGroupingSeparator; + nsAutoPtr mGroupingSize; +}; + +class txPopParams : public txInstruction +{ +public: + TX_DECL_TXINSTRUCTION +}; + +class txProcessingInstruction : public txInstruction +{ +public: + txProcessingInstruction(nsAutoPtr aName); + + TX_DECL_TXINSTRUCTION + + nsAutoPtr mName; +}; + +class txPushNewContext : public txInstruction +{ +public: + txPushNewContext(nsAutoPtr aSelect); + ~txPushNewContext(); + + TX_DECL_TXINSTRUCTION + + + nsresult addSort(nsAutoPtr aSelectExpr, nsAutoPtr aLangExpr, + nsAutoPtr aDataTypeExpr, nsAutoPtr aOrderExpr, + nsAutoPtr aCaseOrderExpr); + + struct SortKey { + SortKey(nsAutoPtr aSelectExpr, nsAutoPtr aLangExpr, + nsAutoPtr aDataTypeExpr, nsAutoPtr aOrderExpr, + nsAutoPtr aCaseOrderExpr); + + nsAutoPtr mSelectExpr; + nsAutoPtr mLangExpr; + nsAutoPtr mDataTypeExpr; + nsAutoPtr mOrderExpr; + nsAutoPtr mCaseOrderExpr; + }; + + nsVoidArray mSortKeys; + nsAutoPtr mSelect; + txInstruction* mBailTarget; +}; + +class txPushNullTemplateRule : public txInstruction +{ +public: + TX_DECL_TXINSTRUCTION +}; + +class txPushParams : public txInstruction +{ +public: + TX_DECL_TXINSTRUCTION +}; + +class txPushRTFHandler : public txInstruction +{ +public: + TX_DECL_TXINSTRUCTION +}; + +class txPushStringHandler : public txInstruction +{ +public: + txPushStringHandler(PRBool aOnlyText); + + TX_DECL_TXINSTRUCTION + + PRBool mOnlyText; +}; + +class txRemoveVariable : public txInstruction +{ +public: + txRemoveVariable(const txExpandedName& aName); + + TX_DECL_TXINSTRUCTION + + txExpandedName mName; +}; + +class txReturn : public txInstruction +{ +public: + TX_DECL_TXINSTRUCTION +}; + +class txSetParam : public txInstruction +{ +public: + txSetParam(const txExpandedName& aName, nsAutoPtr aValue); + + TX_DECL_TXINSTRUCTION + + txExpandedName mName; + nsAutoPtr mValue; +}; + +class txSetVariable : public txInstruction +{ +public: + txSetVariable(const txExpandedName& aName, nsAutoPtr aValue); + + TX_DECL_TXINSTRUCTION + + txExpandedName mName; + nsAutoPtr mValue; +}; + +class txStartElement : public txInstruction +{ +public: + txStartElement(nsAutoPtr aName, nsAutoPtr aNamespace, + txNamespaceMap* aMappings); + + TX_DECL_TXINSTRUCTION + + nsAutoPtr mName; + nsAutoPtr mNamespace; + nsRefPtr mMappings; +}; + +class txStartLREElement : public txInstruction +{ +public: + txStartLREElement(PRInt32 aNamespaceID, nsIAtom* aLocalName, + nsIAtom* aPrefix); + + TX_DECL_TXINSTRUCTION + + PRInt32 mNamespaceID; + nsCOMPtr mLocalName; + nsCOMPtr mPrefix; +}; + +class txText : public txInstruction +{ +public: + txText(const nsAString& aStr, PRBool aDOE); + + TX_DECL_TXINSTRUCTION + + nsString mStr; + PRBool mDOE; +}; + +class txValueOf : public txInstruction +{ +public: + txValueOf(nsAutoPtr aExpr, PRBool aDOE); + + TX_DECL_TXINSTRUCTION + + nsAutoPtr mExpr; + PRBool mDOE; +}; + +#endif //TRANSFRMX_TXINSTRUCTIONS_H diff --git a/mozilla/extensions/transformiix/source/xslt/txMozillaStylesheetCompiler.cpp b/mozilla/extensions/transformiix/source/xslt/txMozillaStylesheetCompiler.cpp new file mode 100644 index 00000000000..c415dd01c5c --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/txMozillaStylesheetCompiler.cpp @@ -0,0 +1,566 @@ +/* -*- 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 "nsCOMArray.h" +#include "nsICharsetAlias.h" +#include "nsIDocument.h" +#include "nsIExpatSink.h" +#include "nsILoadGroup.h" +#include "nsINameSpace.h" +#include "nsINameSpaceManager.h" +#include "nsINodeInfo.h" +#include "nsIParser.h" +#include "nsISyncLoadDOMService.h" +#include "nsIURI.h" +#include "nsIXMLContentSink.h" +#include "nsNetUtil.h" +#include "nsParserCIID.h" +#include "txAtoms.h" +#include "txMozillaXSLTProcessor.h" +#include "txStylesheetCompiler.h" +#include "XMLUtils.h" + +static const char kLoadAsData[] = "loadAsData"; + +class txStylesheetSink : public nsIXMLContentSink, + public nsIExpatSink +{ +public: + txStylesheetSink(txStylesheetCompiler* aCompiler); + virtual ~txStylesheetSink(); + + NS_DECL_ISUPPORTS + NS_DECL_NSIEXPATSINK + + // nsIContentSink + NS_IMETHOD WillBuildModel(void) { return NS_OK; } + NS_IMETHOD DidBuildModel(PRInt32 aQualityLevel); + NS_IMETHOD WillInterrupt(void) { return NS_OK; } + NS_IMETHOD WillResume(void) { return NS_OK; } + NS_IMETHOD SetParser(nsIParser* aParser) { return NS_OK; } + NS_IMETHOD FlushPendingNotifications() { return NS_OK; } + NS_IMETHOD SetDocumentCharset(nsAString& aCharset) { return NS_OK; } + +private: + nsRefPtr mCompiler; + +protected: + // This exists soly to supress a warning from nsDerivedSafe + txStylesheetSink(); +}; + +txStylesheetSink::txStylesheetSink(txStylesheetCompiler* aCompiler) + : mCompiler(aCompiler) +{ +} + +txStylesheetSink::~txStylesheetSink() +{ +} + +NS_IMPL_ISUPPORTS2(txStylesheetSink, nsIXMLContentSink, nsIExpatSink) + +NS_IMETHODIMP +txStylesheetSink::HandleStartElement(const PRUnichar *aName, + const PRUnichar **aAtts, + PRUint32 aAttsCount, + PRUint32 aIndex, + PRUint32 aLineNumber) +{ + nsresult rv = mCompiler->startElement(aName, aAtts, aAttsCount); + if (NS_FAILED(rv)) { + mCompiler->cancel(rv); + return rv; + } + + return NS_OK; +} + +NS_IMETHODIMP +txStylesheetSink::HandleEndElement(const PRUnichar *aName) +{ + nsresult rv = mCompiler->endElement(); + if (NS_FAILED(rv)) { + mCompiler->cancel(rv); + return rv; + } + + return NS_OK; +} + +NS_IMETHODIMP +txStylesheetSink::HandleComment(const PRUnichar *aName) +{ + return NS_OK; +} + +NS_IMETHODIMP +txStylesheetSink::HandleCDataSection(const PRUnichar *aData, + PRUint32 aLength) +{ + return HandleCharacterData(aData, aLength); +} + +NS_IMETHODIMP +txStylesheetSink::HandleDoctypeDecl(const nsAString & aSubset, + const nsAString & aName, + const nsAString & aSystemId, + const nsAString & aPublicId, + nsISupports *aCatalogData) +{ + return NS_OK; +} + +NS_IMETHODIMP +txStylesheetSink::HandleCharacterData(const PRUnichar *aData, + PRUint32 aLength) +{ + nsresult rv = mCompiler->characters(Substring(aData, aData + aLength)); + if (NS_FAILED(rv)) { + mCompiler->cancel(rv); + return rv; + } + + return NS_OK; +} + +NS_IMETHODIMP +txStylesheetSink::HandleProcessingInstruction(const PRUnichar *aTarget, + const PRUnichar *aData) +{ + return NS_OK; +} + +NS_IMETHODIMP +txStylesheetSink::HandleXMLDeclaration(const PRUnichar *aData, + PRUint32 aLength) +{ + return NS_OK; +} + +NS_IMETHODIMP +txStylesheetSink::ReportError(const PRUnichar *aErrorText, + const PRUnichar *aSourceText) +{ + mCompiler->cancel(NS_ERROR_FAILURE); + return NS_OK; +} + +NS_IMETHODIMP +txStylesheetSink::DidBuildModel(PRInt32 aQualityLevel) +{ + return mCompiler->doneLoading(); +} + +class txCompileObserver : public txACompileObserver +{ +public: + txCompileObserver(txMozillaXSLTProcessor* aProcessor, + nsILoadGroup* aLoadGroup); + virtual ~txCompileObserver(); + + TX_DECL_ACOMPILEOBSERVER; + + nsresult startLoad(nsIURI* aUri, txStylesheetSink* aSink, + nsIURI* aReferrerUri); + +protected: + nsAutoRefCnt mRefCnt; + +private: + nsRefPtr mProcessor; + nsCOMPtr mLoadGroup; + +protected: + // This exists soly to supress a warning from nsDerivedSafe + txCompileObserver(); +}; + +txCompileObserver::txCompileObserver(txMozillaXSLTProcessor* aProcessor, + nsILoadGroup* aLoadGroup) + : mProcessor(aProcessor), + mLoadGroup(aLoadGroup) +{ +} + +txCompileObserver::~txCompileObserver() +{ +} + +nsrefcnt +txCompileObserver::AddRef() +{ + return ++mRefCnt; +} + +nsrefcnt +txCompileObserver::Release() +{ + if (--mRefCnt == 0) { + mRefCnt = 1; //stabilize + delete this; + return 0; + } + return mRefCnt; +} + +nsresult +txCompileObserver::loadURI(const nsAString& aUri, + txStylesheetCompiler* aCompiler) +{ + nsCOMPtr uri; + nsresult rv = NS_NewURI(getter_AddRefs(uri), aUri); + NS_ENSURE_SUCCESS(rv, rv); + + nsRefPtr sink = new txStylesheetSink(aCompiler); + NS_ENSURE_TRUE(sink, NS_ERROR_OUT_OF_MEMORY); + + return startLoad(uri, sink, nsnull); +} + +void +txCompileObserver::onDoneCompiling(txStylesheetCompiler* aCompiler, + nsresult aResult) +{ + mProcessor->setStylesheet(aCompiler->getStylesheet()); +} + +nsresult +txCompileObserver::startLoad(nsIURI* aUri, txStylesheetSink* aSink, + nsIURI* aReferrerUri) +{ + nsCOMPtr channel; + nsresult rv = NS_NewChannel(getter_AddRefs(channel), aUri); + NS_ENSURE_SUCCESS(rv, rv); + + channel->SetLoadGroup(mLoadGroup); + + nsCOMPtr httpChannel(do_QueryInterface(channel)); + if (httpChannel) { + httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Accept"), + NS_LITERAL_CSTRING("text/xml,application/xml,application/xhtml+xml,*/*;q=0.1"), + PR_FALSE); + + if (aReferrerUri) { + httpChannel->SetReferrer(aReferrerUri); + } + } + + nsAutoString charset(NS_LITERAL_STRING("UTF-8")); + PRInt32 charsetSource = kCharsetFromDocTypeDefault; + + // check channel's charset... + nsCAutoString charsetVal; + rv = channel->GetContentCharset(charsetVal); + if (NS_SUCCEEDED(rv)) { + nsCOMPtr calias = + do_GetService(NS_CHARSETALIAS_CONTRACTID); + + if (calias) { + nsAutoString preferred; + rv = calias->GetPreferred(NS_ConvertASCIItoUCS2(charsetVal), + preferred); + if (NS_SUCCEEDED(rv)) { + charset = preferred; + charsetSource = kCharsetFromChannel; + } + } + } + + static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID); + nsCOMPtr parser = do_CreateInstance(kCParserCID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + // Set the parser as the stream listener for the document loader... + nsCOMPtr listener = do_QueryInterface(parser, &rv); + NS_ENSURE_TRUE(listener, rv); + + parser->SetDocumentCharset(charset, charsetSource); + parser->SetCommand(kLoadAsData); + parser->SetContentSink(aSink); + parser->Parse(aUri); + + return channel->AsyncOpen(listener, nsnull); +} + +nsresult +TX_LoadSheet(nsIURI* aUri, txMozillaXSLTProcessor* aProcessor, + nsILoadGroup* aLoadGroup, nsIURI* aReferrerUri) +{ + nsCAutoString uri; + aUri->GetSpec(uri); + + nsRefPtr observer = + new txCompileObserver(aProcessor, aLoadGroup); + NS_ENSURE_TRUE(observer, NS_ERROR_OUT_OF_MEMORY); + + nsRefPtr compiler = + new txStylesheetCompiler(NS_ConvertUTF8toUCS2(uri), observer); + NS_ENSURE_TRUE(compiler, NS_ERROR_OUT_OF_MEMORY); + + nsRefPtr sink = new txStylesheetSink(compiler); + NS_ENSURE_TRUE(sink, NS_ERROR_OUT_OF_MEMORY); + + return observer->startLoad(aUri, sink, aReferrerUri); +} + +/** + * handling DOM->txStylesheet + * Observer needs to do synchronous loads. + */ +static nsresult +handleNode(nsIDOMNode* aNode, txStylesheetCompiler* aCompiler) +{ + nsresult rv = NS_OK; + PRUint16 nodetype; + aNode->GetNodeType(&nodetype); + switch (nodetype) { + case nsIDOMNode::ELEMENT_NODE: + { + nsCOMPtr element = do_QueryInterface(aNode); + + nsCOMPtr ni; + element->GetNodeInfo(*getter_AddRefs(ni)); + + PRInt32 namespaceID; + nsCOMPtr prefix, localname; + ni->GetNamespaceID(namespaceID); + ni->GetNameAtom(*getter_AddRefs(localname)); + ni->GetPrefixAtom(*getter_AddRefs(prefix)); + + PRInt32 attsCount; + element->GetAttrCount(attsCount); + nsAutoArrayPtr atts; + if (attsCount > 0) { + atts = new txStylesheetAttr[attsCount]; + NS_ENSURE_TRUE(atts, NS_ERROR_OUT_OF_MEMORY); + + PRInt32 counter; + for (counter = 0; counter < attsCount; ++counter) { + txStylesheetAttr& att = atts[counter]; + element->GetAttrNameAt(counter, att.mNamespaceID, + *getter_AddRefs(att.mLocalName), + *getter_AddRefs(att.mPrefix)); + element->GetAttr(att.mNamespaceID, att.mLocalName, att.mValue); + } + } + + rv = aCompiler->startElement(namespaceID, localname, prefix, atts, + attsCount); + NS_ENSURE_SUCCESS(rv, rv); + + // explicitly destroy the attrs here since we no longer need it + atts = nsnull; + + PRInt32 childCount; + element->ChildCount(childCount); + if (childCount > 0) { + PRInt32 counter = 0; + nsCOMPtr child; + while (NS_SUCCEEDED(element->ChildAt(counter++, *getter_AddRefs(child))) && child) { + nsCOMPtr childNode = do_QueryInterface(child); + rv = handleNode(childNode, aCompiler); + NS_ENSURE_SUCCESS(rv, rv); + } + } + + rv = aCompiler->endElement(); + NS_ENSURE_SUCCESS(rv, rv); + + break; + } + case nsIDOMNode::CDATA_SECTION_NODE: + case nsIDOMNode::TEXT_NODE: + { + nsAutoString chars; + aNode->GetNodeValue(chars); + rv = aCompiler->characters(chars); + NS_ENSURE_SUCCESS(rv, rv); + + break; + } + case nsIDOMNode::DOCUMENT_NODE: + { + nsCOMPtr document = do_QueryInterface(aNode); + PRInt32 childCount; + document->GetChildCount(childCount); + if (childCount > 0) { + PRInt32 counter = 0; + nsCOMPtr child; + while (NS_SUCCEEDED(document->ChildAt(counter++, *getter_AddRefs(child))) && child) { + nsCOMPtr childNode = do_QueryInterface(child); + rv = handleNode(childNode, aCompiler); + NS_ENSURE_SUCCESS(rv, rv); + } + } + break; + } + } + return NS_OK; +} + +class txSyncCompileObserver : public txACompileObserver +{ +public: + txSyncCompileObserver(nsIURI* aReferrerURI); + virtual ~txSyncCompileObserver(); + + TX_DECL_ACOMPILEOBSERVER; + +protected: + nsAutoRefCnt mRefCnt; + +private: + nsCOMPtr mLoadService; + nsCOMPtr mReferrer; + +protected: + // This exists soly to supress a warning from nsDerivedSafe + txSyncCompileObserver(); +}; + +txSyncCompileObserver::txSyncCompileObserver(nsIURI* aReferrer) + : mReferrer(aReferrer) +{ +} + +txSyncCompileObserver::~txSyncCompileObserver() +{ +} + +nsrefcnt +txSyncCompileObserver::AddRef() +{ + return ++mRefCnt; +} + +nsrefcnt +txSyncCompileObserver::Release() +{ + if (--mRefCnt == 0) { + mRefCnt = 1; //stabilize + delete this; + return 0; + } + return mRefCnt; +} + +nsresult +txSyncCompileObserver::loadURI(const nsAString& aUri, + txStylesheetCompiler* aCompiler) +{ + if (!mLoadService) { + mLoadService = + do_GetService("@mozilla.org/content/syncload-dom-service;1"); + NS_ENSURE_TRUE(mLoadService, NS_ERROR_OUT_OF_MEMORY); + } + nsCOMPtr uri; + nsresult rv = NS_NewURI(getter_AddRefs(uri), aUri); + NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr channel; + rv = NS_NewChannel(getter_AddRefs(channel), uri); + NS_ENSURE_SUCCESS(rv, rv); + // This is probably called by js, a loadGroup for the channeldoesn't + // make sense. + + nsCOMPtr httpChannel(do_QueryInterface(channel)); + if (httpChannel) { + httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Accept"), + NS_LITERAL_CSTRING("text/xml,application/xml,application/xhtml+xml,*/*;q=0.1"), + PR_FALSE); + + if (mReferrer) { + httpChannel->SetReferrer(mReferrer); + } + } + nsCOMPtr document; + rv = mLoadService->LoadDocument(channel, mReferrer, + getter_AddRefs(document)); + NS_ENSURE_SUCCESS(rv, rv); + rv = handleNode(document, aCompiler); + if (NS_FAILED(rv)) { + aCompiler->cancel(rv); + return rv; + } + + rv = aCompiler->doneLoading(); + return rv; +} + +void txSyncCompileObserver::onDoneCompiling(txStylesheetCompiler* aCompiler, + nsresult aResult) +{ +} + +nsresult +TX_CompileStylesheet(nsIDOMNode* aNode, txStylesheet** aStylesheet) +{ + nsCOMPtr document; + aNode->GetOwnerDocument(getter_AddRefs(document)); + if (!document) { + document = do_QueryInterface(aNode); + } + + nsCOMPtr doc = do_QueryInterface(document); + nsCOMPtr uri; + doc->GetBaseURL(*getter_AddRefs(uri)); + nsCAutoString baseURI; + uri->GetSpec(baseURI); + + nsRefPtr obs = new txSyncCompileObserver(uri); + NS_ENSURE_TRUE(obs, NS_ERROR_OUT_OF_MEMORY); + NS_ConvertUTF8toUCS2 base(baseURI); + nsRefPtr compiler = + new txStylesheetCompiler(base, obs); + NS_ENSURE_TRUE(compiler, NS_ERROR_OUT_OF_MEMORY); + + nsresult rv = handleNode(document, compiler); + if (NS_FAILED(rv)) { + compiler->cancel(rv); + return rv; + } + + rv = compiler->doneLoading(); + NS_ENSURE_SUCCESS(rv, rv); + + *aStylesheet = compiler->getStylesheet(); + NS_ADDREF(*aStylesheet); + + return NS_OK; +} diff --git a/mozilla/extensions/transformiix/source/xslt/txMozillaXSLTProcessor.cpp b/mozilla/extensions/transformiix/source/xslt/txMozillaXSLTProcessor.cpp index 46431e52c26..3a3878a6742 100644 --- a/mozilla/extensions/transformiix/source/xslt/txMozillaXSLTProcessor.cpp +++ b/mozilla/extensions/transformiix/source/xslt/txMozillaXSLTProcessor.cpp @@ -44,14 +44,14 @@ #include "nsIDocument.h" #include "nsIDOMClassInfo.h" #include "nsIScriptLoader.h" -#include "nsNetUtil.h" -#include "ProcessorState.h" +#include "txExecutionState.h" #include "txMozillaTextOutput.h" #include "txMozillaXMLOutput.h" #include "txSingleNodeContext.h" #include "txURIUtils.h" #include "XMLUtils.h" #include "txUnknownHandler.h" +#include "txXSLTProcessor.h" #include "nsIHTMLDocument.h" /** @@ -60,11 +60,11 @@ class txToDocHandlerFactory : public txAOutputHandlerFactory { public: - txToDocHandlerFactory(ProcessorState* aPs, + txToDocHandlerFactory(txExecutionState* aEs, nsIDOMDocument* aSourceDocument, nsIDOMDocument* aResultDocument, nsITransformObserver* aObserver) - : mPs(aPs), mSourceDocument(aSourceDocument), + : mEs(aEs), mSourceDocument(aSourceDocument), mResultDocument(aResultDocument), mObserver(aObserver) { } @@ -76,7 +76,7 @@ public: TX_DECL_TXAOUTPUTHANDLERFACTORY private: - ProcessorState* mPs; + txExecutionState* mEs; nsCOMPtr mSourceDocument; nsCOMPtr mResultDocument; nsCOMPtr mObserver; @@ -109,7 +109,7 @@ txToDocHandlerFactory::createHandlerWith(txOutputFormat* aFormat, case eMethodNotSet: case eXMLOutput: { - *aHandler = new txUnknownHandler(mPs); + *aHandler = new txUnknownHandler(mEs); break; } @@ -260,129 +260,89 @@ txMozillaXSLTProcessor::TransformDocument(nsIDOMNode* aSourceDOM, return NS_ERROR_DOM_SECURITY_ERR; } + PRUint16 type = 0; + aStyleDOM->GetNodeType(&type); + NS_ENSURE_TRUE(type == nsIDOMNode::ELEMENT_NODE || + type == nsIDOMNode::DOCUMENT_NODE, + NS_ERROR_INVALID_ARG); + + nsresult rv = TX_CompileStylesheet(aStyleDOM, getter_AddRefs(mStylesheet)); + NS_ENSURE_SUCCESS(rv, rv); // Create wrapper for the source document. + mSource = aSourceDOM; nsCOMPtr sourceDOMDocument; - aSourceDOM->GetOwnerDocument(getter_AddRefs(sourceDOMDocument)); + mSource->GetOwnerDocument(getter_AddRefs(sourceDOMDocument)); if (!sourceDOMDocument) { - sourceDOMDocument = do_QueryInterface(aSourceDOM); - NS_ENSURE_TRUE(sourceDOMDocument, NS_ERROR_FAILURE); + sourceDOMDocument = do_QueryInterface(mSource); } + NS_ENSURE_TRUE(sourceDOMDocument, NS_ERROR_FAILURE); Document sourceDocument(sourceDOMDocument); - Node* sourceNode = sourceDocument.createWrapper(aSourceDOM); + Node* sourceNode = sourceDocument.createWrapper(mSource); 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(sourceNode, &xslDocument); - - // XXX Need to add error observers - - // Set current txIEvalContext - txSingleNodeContext evalContext(sourceNode, &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, + txExecutionState es(mStylesheet); + txToDocHandlerFactory handlerFactory(&es, sourceDOMDocument, aOutputDoc, nsnull); - ps.mOutputHandlerFactory = &handlerFactory; + es.mOutputHandlerFactory = &handlerFactory; + + es.init(sourceNode, &mVariables); // Process root of XML source document - txXSLTProcessor::transform(&ps); + txXSLTProcessor::execute(es); + es.end(); return NS_OK; } NS_IMETHODIMP -txMozillaXSLTProcessor::TransformDocument(nsIDOMNode* aSourceDOM, - nsIDOMNode* aStyleDOM, - nsITransformObserver* aObserver, - nsIDOMDocument** aOutputDoc) +txMozillaXSLTProcessor::SetTransformObserver(nsITransformObserver* aObserver) { - NS_ENSURE_ARG(aSourceDOM); - NS_ENSURE_ARG(aStyleDOM); - NS_ASSERTION(aObserver, "no observer"); - NS_ENSURE_ARG_POINTER(aOutputDoc); + mObserver = aObserver; + return NS_OK; +} + +nsresult +txMozillaXSLTProcessor::SetSourceContentModel(nsIDOMNode* aSourceDOM) +{ + mSource = aSourceDOM; + if (mStylesheet) { + return DoTransform(); + } + return NS_OK; +} + +nsresult +txMozillaXSLTProcessor::DoTransform() +{ + NS_ENSURE_TRUE(mSource, NS_ERROR_UNEXPECTED); + NS_ENSURE_TRUE(mStylesheet, NS_ERROR_UNEXPECTED); + NS_ASSERTION(mObserver, "no observer"); // Create wrapper for the source document. nsCOMPtr sourceDOMDocument; - aSourceDOM->GetOwnerDocument(getter_AddRefs(sourceDOMDocument)); + mSource->GetOwnerDocument(getter_AddRefs(sourceDOMDocument)); if (!sourceDOMDocument) { - sourceDOMDocument = do_QueryInterface(aSourceDOM); + sourceDOMDocument = do_QueryInterface(mSource); } NS_ENSURE_TRUE(sourceDOMDocument, NS_ERROR_FAILURE); Document sourceDocument(sourceDOMDocument); - Node* sourceNode = sourceDocument.createWrapper(aSourceDOM); + Node* sourceNode = sourceDocument.createWrapper(mSource); 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(sourceNode, &xslDocument); + txExecutionState es(mStylesheet); // XXX Need to add error observers - // Set current txIEvalContext - txSingleNodeContext evalContext(sourceNode, &ps); - ps.setEvalContext(&evalContext); + txToDocHandlerFactory handlerFactory(&es, sourceDOMDocument, nsnull, + mObserver); + es.mOutputHandlerFactory = &handlerFactory; - // 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; + es.init(sourceNode, &mVariables); // Process root of XML source document - txXSLTProcessor::transform(&ps); + txXSLTProcessor::execute(es); + es.end(); - txAOutputXMLEventHandler* handler = - NS_STATIC_CAST(txAOutputXMLEventHandler*, ps.mOutputHandler); - handler->getOutputDocument(aOutputDoc); return NS_OK; } @@ -394,27 +354,15 @@ txMozillaXSLTProcessor::ImportStylesheet(nsIDOMNode *aStyle) return NS_ERROR_DOM_SECURITY_ERR; } - if (mStylesheet) { - return NS_ERROR_NOT_IMPLEMENTED; - } - PRUint16 type = 0; aStyle->GetNodeType(&type); - switch (type) { - case nsIDOMNode::ELEMENT_NODE: - aStyle->GetOwnerDocument(getter_AddRefs(mStylesheetDocument)); - break; + NS_ENSURE_TRUE(type == nsIDOMNode::ELEMENT_NODE || + type == nsIDOMNode::DOCUMENT_NODE, + NS_ERROR_INVALID_ARG); - case nsIDOMNode::DOCUMENT_NODE: - mStylesheetDocument = do_QueryInterface(aStyle); - break; + nsresult rv = TX_CompileStylesheet(aStyle, getter_AddRefs(mStylesheet)); + NS_ENSURE_SUCCESS(rv, rv); - default: - return NS_ERROR_INVALID_ARG; - } - - mStylesheet = aStyle; - return NS_OK; } @@ -441,45 +389,22 @@ txMozillaXSLTProcessor::TransformToDocument(nsIDOMNode *aSource, Node* sourceNode = sourceDocument.createWrapper(aSource); NS_ENSURE_TRUE(sourceNode, NS_ERROR_FAILURE); - // Create wrapper for the style document. - Document xslDocument(mStylesheetDocument); - - // 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(sourceNode, &xslDocument); + txExecutionState es(mStylesheet); // XXX Need to add error observers - // Set current txIEvalContext - txSingleNodeContext evalContext(sourceNode, &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, + txToDocHandlerFactory handlerFactory(&es, sourceDOMDocument, nsnull, nsnull); - ps.mOutputHandlerFactory = &handlerFactory; + es.mOutputHandlerFactory = &handlerFactory; + + es.init(sourceNode, &mVariables); // Process root of XML source document - txXSLTProcessor::transform(&ps); + txXSLTProcessor::execute(es); + es.end(); txAOutputXMLEventHandler* handler = - NS_STATIC_CAST(txAOutputXMLEventHandler*, ps.mOutputHandler); + NS_STATIC_CAST(txAOutputXMLEventHandler*, es.mOutputHandler); handler->getOutputDocument(aResult); return NS_OK; @@ -511,43 +436,20 @@ txMozillaXSLTProcessor::TransformToFragment(nsIDOMNode *aSource, Node* sourceNode = sourceDocument.createWrapper(aSource); NS_ENSURE_TRUE(sourceNode, NS_ERROR_FAILURE); - // Create wrapper for the style document. - Document xslDocument(mStylesheetDocument); - - // 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(sourceNode, &xslDocument); + txExecutionState es(mStylesheet); // XXX Need to add error observers - // Set current txIEvalContext - txSingleNodeContext evalContext(sourceNode, &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); + nsresult rv = aOutput->CreateDocumentFragment(aResult); NS_ENSURE_SUCCESS(rv, rv); txToFragmentHandlerFactory handlerFactory(*aResult); - ps.mOutputHandlerFactory = &handlerFactory; + es.mOutputHandlerFactory = &handlerFactory; + + es.init(sourceNode, &mVariables); // Process root of XML source document - txXSLTProcessor::transform(&ps); + txXSLTProcessor::execute(es); + es.end(); return NS_OK; } @@ -671,6 +573,23 @@ txMozillaXSLTProcessor::Reset() return NS_OK; } +NS_IMETHODIMP +txMozillaXSLTProcessor::LoadStyleSheet(nsIURI* aUri, nsILoadGroup* aLoadGroup, + nsIURI* aReferrerUri) +{ + return TX_LoadSheet(aUri, this, aLoadGroup, aReferrerUri); +} + +nsresult +txMozillaXSLTProcessor::setStylesheet(txStylesheet* aStylesheet) +{ + mStylesheet = aStylesheet; + if (mSource) { + return DoTransform(); + } + return NS_OK; +} + /* static*/ nsresult txVariable::Convert(nsIVariant *aValue, ExprResult** aResult) diff --git a/mozilla/extensions/transformiix/source/xslt/txMozillaXSLTProcessor.h b/mozilla/extensions/transformiix/source/xslt/txMozillaXSLTProcessor.h index dd843ff8a6e..e3057473f8d 100644 --- a/mozilla/extensions/transformiix/source/xslt/txMozillaXSLTProcessor.h +++ b/mozilla/extensions/transformiix/source/xslt/txMozillaXSLTProcessor.h @@ -47,18 +47,24 @@ #include "nsVoidArray.h" #include "nsWeakPtr.h" #include "txExpandedNameMap.h" -#include "XSLTProcessor.h" #include "nsIDOMNode.h" #include "txXMLEventHandler.h" #include "nsIDOMDocument.h" #include "nsIXSLTProcessorObsolete.h" +#include "txXSLTProcessor.h" +#include "nsVoidArray.h" +#include "txStylesheet.h" +#include "nsAutoPtr.h" + +class nsIURI; +class nsIXMLContentSink; /* 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" +"@mozilla.org/document-transformer;1?type=text/xslt" class txVariable : public txIGlobalParameter { @@ -133,15 +139,27 @@ public: NS_DECL_NSIXSLTPROCESSOROBSOLETE // nsIDocumentTransformer interface - NS_IMETHOD TransformDocument(nsIDOMNode *aSourceDOM, - nsIDOMNode *aStyleDOM, - nsITransformObserver *aObserver, - nsIDOMDocument **_retval); + NS_IMETHOD SetTransformObserver(nsITransformObserver* aObserver); + NS_IMETHOD LoadStyleSheet(nsIURI* aUri, nsILoadGroup* aLoadGroup, + nsIURI* aReferrerUri); + NS_IMETHOD SetSourceContentModel(nsIDOMNode* aSource); + NS_IMETHOD CancelLoads() {return NS_OK;}; -protected: - nsCOMPtr mStylesheet; - nsCOMPtr mStylesheetDocument; + nsresult setStylesheet(txStylesheet* aStylesheet); + +private: + nsresult DoTransform(); + + nsRefPtr mStylesheet; + nsCOMPtr mSource; + nsCOMPtr mObserver; txExpandedNameMap mVariables; }; +extern nsresult TX_LoadSheet(nsIURI* aUri, txMozillaXSLTProcessor* aProcessor, + nsILoadGroup* aLoadGroup, nsIURI* aReferrerUri); + +extern nsresult TX_CompileStylesheet(nsIDOMNode* aNode, + txStylesheet** aStylesheet); + #endif diff --git a/mozilla/extensions/transformiix/source/xslt/txPatternParser.cpp b/mozilla/extensions/transformiix/source/xslt/txPatternParser.cpp index a606d31e476..02b17990e4d 100644 --- a/mozilla/extensions/transformiix/source/xslt/txPatternParser.cpp +++ b/mozilla/extensions/transformiix/source/xslt/txPatternParser.cpp @@ -44,12 +44,11 @@ #include "txIXPathContext.h" txPattern* txPatternParser::createPattern(const nsAFlatString& aPattern, - txIParseContext* aContext, - ProcessorState* aPs) + txIParseContext* aContext) { txPattern* pattern = 0; ExprLexer lexer(aPattern); - nsresult rv = createUnionPattern(lexer, aContext, aPs, pattern); + nsresult rv = createUnionPattern(lexer, aContext, pattern); if (NS_FAILED(rv)) { // XXX error report parsing error return 0; @@ -59,13 +58,12 @@ txPattern* txPatternParser::createPattern(const nsAFlatString& aPattern, nsresult txPatternParser::createUnionPattern(ExprLexer& aLexer, txIParseContext* aContext, - ProcessorState* aPs, txPattern*& aPattern) { nsresult rv = NS_OK; txPattern* locPath = 0; - rv = createLocPathPattern(aLexer, aContext, aPs, locPath); + rv = createLocPathPattern(aLexer, aContext, locPath); if (NS_FAILED(rv)) return rv; @@ -96,7 +94,7 @@ nsresult txPatternParser::createUnionPattern(ExprLexer& aLexer, aLexer.nextToken(); do { - rv = createLocPathPattern(aLexer, aContext, aPs, locPath); + rv = createLocPathPattern(aLexer, aContext, locPath); if (NS_FAILED(rv)) { delete unionPattern; return rv; @@ -123,7 +121,6 @@ nsresult txPatternParser::createUnionPattern(ExprLexer& aLexer, nsresult txPatternParser::createLocPathPattern(ExprLexer& aLexer, txIParseContext* aContext, - ProcessorState* aPs, txPattern*& aPattern) { nsresult rv = NS_OK; @@ -157,7 +154,7 @@ nsresult txPatternParser::createLocPathPattern(ExprLexer& aLexer, rv = createIdPattern(aLexer, stepPattern); } else if (nameAtom == txXSLTAtoms::key) { - rv = createKeyPattern(aLexer, aContext, aPs, stepPattern); + rv = createKeyPattern(aLexer, aContext, stepPattern); } if (NS_FAILED(rv)) return rv; @@ -246,7 +243,6 @@ nsresult txPatternParser::createIdPattern(ExprLexer& aLexer, nsresult txPatternParser::createKeyPattern(ExprLexer& aLexer, txIParseContext* aContext, - ProcessorState* aPs, txPattern*& aPattern) { // check for '(' Literal, Literal ')' @@ -270,7 +266,7 @@ nsresult txPatternParser::createKeyPattern(ExprLexer& aLexer, if (NS_FAILED(rv)) return rv; - aPattern = new txKeyPattern(aPs, prefix, localName, namespaceID, value); + aPattern = new txKeyPattern(prefix, localName, namespaceID, value); return aPattern ? NS_OK : NS_ERROR_OUT_OF_MEMORY; } diff --git a/mozilla/extensions/transformiix/source/xslt/txPatternParser.h b/mozilla/extensions/transformiix/source/xslt/txPatternParser.h index ae8fa57c695..e4c95fda667 100644 --- a/mozilla/extensions/transformiix/source/xslt/txPatternParser.h +++ b/mozilla/extensions/transformiix/source/xslt/txPatternParser.h @@ -46,22 +46,18 @@ class txPatternParser : public ExprParser { public: static txPattern* createPattern(const nsAFlatString& aPattern, - txIParseContext* aContext, - ProcessorState* aPs); + txIParseContext* aContext); protected: static nsresult createUnionPattern(ExprLexer& aLexer, txIParseContext* aContext, - ProcessorState* aPs, txPattern*& aPattern); static nsresult createLocPathPattern(ExprLexer& aLexer, txIParseContext* aContext, - ProcessorState* aPs, txPattern*& aPattern); static nsresult createIdPattern(ExprLexer& aLexer, txPattern*& aPattern); static nsresult createKeyPattern(ExprLexer& aLexer, txIParseContext* aContext, - ProcessorState* aPs, txPattern*& aPattern); static nsresult createStepPattern(ExprLexer& aLexer, txIParseContext* aContext, diff --git a/mozilla/extensions/transformiix/source/xslt/txStandaloneStylesheetCompiler.cpp b/mozilla/extensions/transformiix/source/xslt/txStandaloneStylesheetCompiler.cpp new file mode 100644 index 00000000000..e7285119aa4 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/txStandaloneStylesheetCompiler.cpp @@ -0,0 +1,346 @@ +/* -*- 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) 2003 + * 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 "txStandaloneStylesheetCompiler.h" +#include "txStylesheetCompiler.h" +#include "txURIUtils.h" +#include "xmlparse.h" + +/** + * Implementation of an In-Memory DOM based XML parser. The actual XML + * parsing is provided by EXPAT. + */ +class txDriver : public txACompileObserver +{ + public: + nsresult parse(istream& aInputStream, const nsAString& aUri); + const nsAString& getErrorString(); + + /** + * Expat handlers + */ + int StartElement(const XML_Char *aName, const XML_Char **aAtts); + int EndElement(const XML_Char* aName); + void CharacterData(const XML_Char* aChars, int aLength); + int ExternalEntityRef(const XML_Char *aContext, const XML_Char *aBase, + const XML_Char *aSystemId, + const XML_Char *aPublicId); + + TX_DECL_ACOMPILEOBSERVER; + + nsRefPtr mCompiler; + protected: + void createErrorString(); + nsString mErrorString; + XML_Parser mExpatParser; + nsAutoRefCnt mRefCnt; +}; + +nsresult +TX_CompileStylesheetPath(const nsAString& aHref, txStylesheet** aResult) +{ + *aResult = nsnull; + nsAutoString errMsg; + istream* xslInput = URIUtils::getInputStream(aHref, errMsg); + if (!xslInput) { + return NS_ERROR_FAILURE; + } + nsRefPtr driver = new txDriver(); + if (!driver) { + return NS_ERROR_OUT_OF_MEMORY; + } + driver->mCompiler = new txStylesheetCompiler(aHref, driver); + if (!driver->mCompiler) { + return NS_ERROR_OUT_OF_MEMORY; + } + nsresult rv = driver->parse(*xslInput, aHref); + if (NS_FAILED(rv)) { + return rv; + }; + *aResult = driver->mCompiler->getStylesheet(); + NS_ADDREF(*aResult); + return NS_OK; +} + +/** + * expat C stub handlers + */ + +// shortcut macro for redirection into txDriver method calls +#define TX_DRIVER(_userData) NS_STATIC_CAST(txDriver*, _userData) + +PR_STATIC_CALLBACK(int) +startElement(void *aUserData, const XML_Char *aName, const XML_Char **aAtts) +{ + NS_ENSURE_TRUE(aUserData, XML_ERROR_NONE); + return TX_DRIVER(aUserData)->StartElement(aName, aAtts); +} + +PR_STATIC_CALLBACK(int) +endElement(void *aUserData, const XML_Char* aName) +{ + NS_ENSURE_TRUE(aUserData, XML_ERROR_NONE); + return TX_DRIVER(aUserData)->EndElement(aName); +} + +PR_STATIC_CALLBACK(void) +charData(void* aUserData, const XML_Char* aChars, int aLength) +{ + if (!aUserData) { + NS_WARNING("no userData in charData handler"); + return; + } + TX_DRIVER(aUserData)->CharacterData(aChars, aLength); +} + +PR_STATIC_CALLBACK(int) +externalEntityRefHandler(XML_Parser aParser, + const XML_Char *aContext, + const XML_Char *aBase, + const XML_Char *aSystemId, + const XML_Char *aPublicId) +{ + // aParser is aUserData is the txDriver, + // we set that in txDriver::parse + NS_ENSURE_TRUE(aParser, XML_ERROR_NONE); + return TX_DRIVER(aParser)->ExternalEntityRef(aContext, aBase, + aSystemId, aPublicId); +} + + +/** + * Parses the given input stream and returns a DOM Document. + * A NULL pointer will be returned if errors occurred + */ +nsresult +txDriver::parse(istream& aInputStream, const nsAString& aUri) +{ + mErrorString.Truncate(); + if (!aInputStream) { + mErrorString.Append(NS_LITERAL_STRING("unable to parse xml: invalid or unopen stream encountered.")); + return NS_ERROR_FAILURE; + } + mExpatParser = XML_ParserCreate(nsnull); + if (!mExpatParser) { + return NS_ERROR_OUT_OF_MEMORY; + } + + XML_SetUserData(mExpatParser, this); + XML_SetElementHandler(mExpatParser, startElement, endElement); + XML_SetCharacterDataHandler(mExpatParser, charData); +#ifdef XML_DTD + XML_SetParamEntityParsing(mExpatParser, XML_PARAM_ENTITY_PARSING_ALWAYS); +#endif + XML_SetExternalEntityRefHandler(mExpatParser, externalEntityRefHandler); + XML_SetExternalEntityRefHandlerArg(mExpatParser, this); + XML_SetBase(mExpatParser, + (const XML_Char*)(PromiseFlatString(aUri).get())); + + const int bufferSize = 1024; + char buf[bufferSize]; + PRBool done; + int success; + do { + aInputStream.read(buf, bufferSize); + done = aInputStream.eof(); + success = XML_Parse(mExpatParser, buf, aInputStream.gcount(), done); + if (!success) { + createErrorString(); + done = MB_TRUE; + } + } while (!done); + aInputStream.clear(); + + // clean up + XML_ParserFree(mExpatParser); + mCompiler->doneLoading(); + if (!success) { + return NS_ERROR_FAILURE; + } + return NS_OK; +} + +const nsAString& +txDriver::getErrorString() +{ + return mErrorString; +} + +int +txDriver::StartElement(const XML_Char *aName, const XML_Char **aAtts) +{ + PRInt32 attcount = 0; + const XML_Char** atts = aAtts; + while (*atts) { + ++atts; + ++attcount; + } + nsresult rv = + mCompiler->startElement(NS_STATIC_CAST(const PRUnichar*, aName), + NS_STATIC_CAST(const PRUnichar**, aAtts), + attcount/2); + if (NS_FAILED(rv)) { + mCompiler->cancel(rv); + return XML_ERROR_SYNTAX; + } + return XML_ERROR_NONE; +} + +int +txDriver::EndElement(const XML_Char* aName) +{ + nsresult rv = mCompiler->endElement(); + if (NS_FAILED(rv)) { + mCompiler->cancel(rv); + return XML_ERROR_SYNTAX; + } + return XML_ERROR_NONE; +} + +void +txDriver::CharacterData(const XML_Char* aChars, int aLength) +{ + const PRUnichar* pChars = NS_STATIC_CAST(const PRUnichar*, aChars); + // ignore rv, as this expat handler returns void + nsresult rv = mCompiler->characters(Substring(pChars, pChars + aLength)); + if (NS_FAILED(rv)) { + mCompiler->cancel(rv); + } +} + +int +txDriver::ExternalEntityRef(const XML_Char *aContext, const XML_Char *aBase, + const XML_Char *aSystemId, + const XML_Char *aPublicId) +{ + if (aPublicId) { + // not supported, this is "http://some.site.net/foo.dtd" stuff + return XML_ERROR_EXTERNAL_ENTITY_HANDLING; + } + nsAutoString absUrl; + URIUtils::resolveHref(nsDependentString((PRUnichar*)aSystemId), + nsDependentString((PRUnichar*)aBase), absUrl); + istream* extInput = URIUtils::getInputStream(absUrl, mErrorString); + if (!extInput) { + return XML_ERROR_EXTERNAL_ENTITY_HANDLING; + } + XML_Parser parent = mExpatParser; + mExpatParser = + XML_ExternalEntityParserCreate(mExpatParser, aContext, nsnull); + if (!mExpatParser) { + mExpatParser = parent; + delete extInput; + return XML_ERROR_EXTERNAL_ENTITY_HANDLING; + } + XML_SetBase(mExpatParser, absUrl.get()); + + const int bufSize = 1024; + char buffer[bufSize]; + int result; + PRBool done; + do { + extInput->read(buffer, bufSize); + done = extInput->eof(); + if (!(result = + XML_Parse(mExpatParser, buffer, extInput->gcount(), done))) { + createErrorString(); + mErrorString.Append(PRUnichar('\n')); + done = MB_TRUE; + } + } while (!done); + + delete extInput; + XML_ParserFree(mExpatParser); + + mExpatParser = parent; + + return result; +} + +void +txDriver::createErrorString() +{ + XML_Error errCode = XML_GetErrorCode(mExpatParser); + mErrorString.AppendWithConversion(XML_ErrorString(errCode)); + mErrorString.Append(NS_LITERAL_STRING(" at line ")); + mErrorString.AppendInt(XML_GetCurrentLineNumber(mExpatParser)); + mErrorString.Append(NS_LITERAL_STRING(" in ")); + mErrorString.Append((const PRUnichar*)XML_GetBase(mExpatParser)); +} + +/** + * txACompileObserver implementation + */ + +nsrefcnt +txDriver::AddRef() +{ + return ++mRefCnt; +} + +nsrefcnt +txDriver::Release() +{ + if (--mRefCnt == 0) { + mRefCnt = 1; //stabilize + delete this; + return 0; + } + return mRefCnt; +} + +void +txDriver::onDoneCompiling(txStylesheetCompiler* aCompiler, nsresult aResult) +{ +} + +nsresult +txDriver::loadURI(const nsAString& aUri, txStylesheetCompiler* aCompiler) +{ + nsAutoString errMsg; + istream* xslInput = URIUtils::getInputStream(aUri, errMsg); + if (!xslInput) { + return NS_ERROR_FAILURE; + } + nsRefPtr driver = new txDriver(); + if (!driver) { + return NS_ERROR_OUT_OF_MEMORY; + } + driver->mCompiler = aCompiler; + return driver->parse(*xslInput, aUri); +} diff --git a/mozilla/extensions/transformiix/source/xslt/txStandaloneStylesheetCompiler.h b/mozilla/extensions/transformiix/source/xslt/txStandaloneStylesheetCompiler.h new file mode 100644 index 00000000000..9d6ee3a89ca --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/txStandaloneStylesheetCompiler.h @@ -0,0 +1,55 @@ +/* -*- 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) 2003 + * 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 ***** */ + +#ifndef __TX_STANDALONE_STYLESHEET_COMPILER_H__ +#define __TX_STANDALONE_STYLESHEET_COMPILER_H__ + +#include "txStylesheet.h" + +/** + * API to load XML files into compiled stylesheets. + * Parsing is done by expat. + */ + +/** + * Parse a stylesheet from the aPath. + */ +nsresult +TX_CompileStylesheetPath(const nsAString& aHref, txStylesheet** aResult); + +#endif // __TX_STANDALONE_STYLESHEET_COMPILER_H__ diff --git a/mozilla/extensions/transformiix/source/xslt/txStandaloneXSLTProcessor.cpp b/mozilla/extensions/transformiix/source/xslt/txStandaloneXSLTProcessor.cpp index f01eccbef5e..6b8c3780d0a 100644 --- a/mozilla/extensions/transformiix/source/xslt/txStandaloneXSLTProcessor.cpp +++ b/mozilla/extensions/transformiix/source/xslt/txStandaloneXSLTProcessor.cpp @@ -39,6 +39,7 @@ * ***** END LICENSE BLOCK ***** */ #include "txStandaloneXSLTProcessor.h" +#include "txStandaloneStylesheetCompiler.h" #include "nsCRT.h" #include "nsReadableUtils.h" #include "txHTMLOutput.h" @@ -48,15 +49,17 @@ #include "txURIUtils.h" #include "txXMLParser.h" +TX_IMPL_DOM_STATICS; + /** * Output Handler Factory */ class txStandaloneHandlerFactory : public txAOutputHandlerFactory { public: - txStandaloneHandlerFactory(ProcessorState* aPs, + txStandaloneHandlerFactory(txExecutionState* aEs, ostream* aStream) - : mPs(aPs), mStream(aStream) + : mEs(aEs), mStream(aStream) { } @@ -67,7 +70,7 @@ public: TX_DECL_TXAOUTPUTHANDLERFACTORY; private: - ProcessorState* mPs; + txExecutionState* mEs; ostream* mStream; }; @@ -90,7 +93,7 @@ txStandaloneHandlerFactory::createHandlerWith(txOutputFormat* aFormat, break; case eMethodNotSet: - *aHandler = new txUnknownHandler(mPs); + *aHandler = new txUnknownHandler(mEs); break; } NS_ENSURE_TRUE(*aHandler, NS_ERROR_OUT_OF_MEMORY); @@ -150,16 +153,17 @@ txStandaloneXSLTProcessor::transform(nsACString& aXMLPath, if (!xmlDoc) { return NS_ERROR_FAILURE; } - Document* xslDoc = parsePath(aXSLPath, aErr); - if (!xslDoc) { + nsRefPtr style; + nsresult rv = TX_CompileStylesheetPath(NS_ConvertASCIItoUCS2(aXSLPath), + getter_AddRefs(style)); + if (NS_FAILED(rv)) { delete xmlDoc; - return NS_ERROR_FAILURE; + return rv; } // transform - nsresult rv = transform(xmlDoc, xslDoc, aOut, aErr); + rv = transform(xmlDoc, style, aOut, aErr); delete xmlDoc; - delete xslDoc; return rv; } @@ -181,15 +185,12 @@ txStandaloneXSLTProcessor::transform(Document* aXMLDoc, ostream& aOut, nsAutoString stylePath; getHrefFromStylesheetPI(*aXMLDoc, stylePath); - Document* xslDoc = parsePath(NS_LossyConvertUCS2toASCII(stylePath), aErr); - if (!xslDoc) { - return NS_ERROR_FAILURE; - } + nsRefPtr style; + nsresult rv = TX_CompileStylesheetPath(stylePath, getter_AddRefs(style)); // transform - nsresult rv = transform(aXMLDoc, xslDoc, aOut, aErr); + rv = transform(aXMLDoc, style, aOut, aErr); - delete xslDoc; return rv; } @@ -198,46 +199,28 @@ txStandaloneXSLTProcessor::transform(Document* aXMLDoc, ostream& aOut, * and prints the results to the given ostream argument */ nsresult -txStandaloneXSLTProcessor::transform(Document* aSource, Node* aStylesheet, +txStandaloneXSLTProcessor::transform(Document* aSource, + txStylesheet* 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); + // Create a new txEvalState + txExecutionState es(aStylesheet); - ps.addErrorObserver(aErr); + // XXX todo es.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; + txStandaloneHandlerFactory handlerFactory(&es, &aOut); #ifndef XP_WIN bool sync = aOut.sync_with_stdio(false); #endif + es.mOutputHandlerFactory = &handlerFactory; + + es.init(aSource, nsnull); + // Process root of XML source document - txXSLTProcessor::transform(&ps); + txXSLTProcessor::execute(es); + es.end(); + #ifndef XP_WIN aOut.sync_with_stdio(sync); #endif diff --git a/mozilla/extensions/transformiix/source/xslt/txStandaloneXSLTProcessor.h b/mozilla/extensions/transformiix/source/xslt/txStandaloneXSLTProcessor.h index c0403ca66a1..bca42e91bbe 100644 --- a/mozilla/extensions/transformiix/source/xslt/txStandaloneXSLTProcessor.h +++ b/mozilla/extensions/transformiix/source/xslt/txStandaloneXSLTProcessor.h @@ -41,7 +41,10 @@ #ifndef TRANSFRMX_TXSTANDALONEXSLTPROCESSOR_H #define TRANSFRMX_TXSTANDALONEXSLTPROCESSOR_H -#include "XSLTProcessor.h" +#include "txStylesheet.h" +#include "txXSLTProcessor.h" +#include "ErrorObserver.h" + #ifndef __BORLANDC__ #include #include @@ -130,7 +133,7 @@ public: * @param aErr error observer * @result NS_OK if transformation was successful */ - nsresult transform(Document* aXMLDoc, Node* aXSLNode, + nsresult transform(Document* aXMLDoc, txStylesheet* aXSLNode, ostream& aOut, ErrorObserver& aErr); protected: diff --git a/mozilla/extensions/transformiix/source/xslt/txStylesheet.cpp b/mozilla/extensions/transformiix/source/xslt/txStylesheet.cpp new file mode 100644 index 00000000000..7e18d4bf808 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/txStylesheet.cpp @@ -0,0 +1,684 @@ +/* -*- 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 + * Jonas Sicking. + * Portions created by the Initial Developer are Copyright (C) 2002 + * Jonas Sicking. All Rights Reserved. + * + * Contributor(s): + * Jonas Sicking + * + * 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 "txStylesheet.h" +#include "Expr.h" +#include "txXSLTPatterns.h" +#include "txToplevelItems.h" +#include "txInstructions.h" +#include "primitives.h" +#include "XSLTFunctions.h" +#include "TxLog.h" +#include "txKey.h" + +txStylesheet::txStylesheet() + : mRootFrame(nsnull), + mNamedTemplates(PR_FALSE), + mDecimalFormats(PR_TRUE), + mAttributeSets(PR_FALSE), + mGlobalVariables(PR_TRUE), + mKeys(PR_TRUE) +{ +} + +nsresult +txStylesheet::init() +{ + mRootFrame = new ImportFrame; + NS_ENSURE_TRUE(mRootFrame, NS_ERROR_OUT_OF_MEMORY); + + // Create default templates + // element/root template + txInstruction** instrp = mContainerTemplate.StartAssignment(); + *instrp = new txPushParams; + NS_ENSURE_TRUE(*instrp, NS_ERROR_OUT_OF_MEMORY); + + nsAutoPtr nt(new txNodeTypeTest(txNodeTypeTest::NODE_TYPE)); + NS_ENSURE_TRUE(nt, NS_ERROR_OUT_OF_MEMORY); + + nsAutoPtr nodeExpr(new LocationStep(nt, LocationStep::CHILD_AXIS)); + NS_ENSURE_TRUE(nodeExpr, NS_ERROR_OUT_OF_MEMORY); + + instrp = &(*instrp)->mNext; + txPushNewContext* pushContext = new txPushNewContext(nodeExpr); + *instrp = pushContext; + NS_ENSURE_TRUE(*instrp, NS_ERROR_OUT_OF_MEMORY); + + instrp = &(*instrp)->mNext; + txApplyDefaultElementTemplate* applyTemplates = + new txApplyDefaultElementTemplate; + *instrp = applyTemplates; + NS_ENSURE_TRUE(*instrp, NS_ERROR_OUT_OF_MEMORY); + + instrp = &(*instrp)->mNext; + *instrp = new txLoopNodeSet(applyTemplates); + NS_ENSURE_TRUE(*instrp, NS_ERROR_OUT_OF_MEMORY); + + instrp = &(*instrp)->mNext; + pushContext->mBailTarget = *instrp = new txPopParams; + NS_ENSURE_TRUE(*instrp, NS_ERROR_OUT_OF_MEMORY); + + instrp = &(*instrp)->mNext; + *instrp = new txReturn(); + NS_ENSURE_TRUE(*instrp, NS_ERROR_OUT_OF_MEMORY); + + // attribute/textnode template + nt = new txNodeTypeTest(txNodeTypeTest::NODE_TYPE); + NS_ENSURE_TRUE(nt, NS_ERROR_OUT_OF_MEMORY); + + nodeExpr = new LocationStep(nt, LocationStep::SELF_AXIS); + NS_ENSURE_TRUE(nodeExpr, NS_ERROR_OUT_OF_MEMORY); + + mCharactersTemplate = new txValueOf(nodeExpr, PR_FALSE); + NS_ENSURE_TRUE(mContainerTemplate, NS_ERROR_OUT_OF_MEMORY); + + mCharactersTemplate->mNext = new txReturn(); + NS_ENSURE_TRUE(mContainerTemplate->mNext, NS_ERROR_OUT_OF_MEMORY); + + // pi/comment/namespace template + mEmptyTemplate = new txReturn(); + NS_ENSURE_TRUE(mEmptyTemplate, NS_ERROR_OUT_OF_MEMORY); + + return NS_OK; +} + +txStylesheet::~txStylesheet() +{ + // Delete all ImportFrames + delete mRootFrame; + txListIterator frameIter(&mImportFrames); + while (frameIter.hasNext()) { + delete NS_STATIC_CAST(ImportFrame*, frameIter.next()); + } + + txListIterator instrIter(&mTemplateInstructions); + while (instrIter.hasNext()) { + delete NS_STATIC_CAST(txInstruction*, instrIter.next()); + } + + // We can't make the map own its values because then we wouldn't be able + // to merge attributesets of the same name + txExpandedNameMap::iterator attrSetIter(mAttributeSets); + while (attrSetIter.next()) { + delete attrSetIter.value(); + } +} + +txInstruction* +txStylesheet::findTemplate(Node* aNode, + const txExpandedName& aMode, + txIMatchContext* aContext, + ImportFrame* aImportedBy, + ImportFrame** aImportFrame) +{ + NS_ASSERTION(aImportFrame, "missing ImportFrame pointer"); + NS_ASSERTION(aNode, "missing node"); + + *aImportFrame = nsnull; + txInstruction* matchTemplate = nsnull; + ImportFrame* endFrame = nsnull; + txListIterator frameIter(&mImportFrames); + + if (aImportedBy) { + ImportFrame* curr = NS_STATIC_CAST(ImportFrame*, frameIter.next()); + while (curr != aImportedBy) { + curr = NS_STATIC_CAST(ImportFrame*, frameIter.next()); + } + endFrame = aImportedBy->mFirstNotImported; + } + +#ifdef PR_LOGGING + txPattern* match = 0; +#endif + + ImportFrame* frame; + while (!matchTemplate && + (frame = NS_STATIC_CAST(ImportFrame*, frameIter.next())) && + frame != endFrame) { + + // get templatelist for this mode + txList* templates = + NS_STATIC_CAST(txList*, frame->mMatchableTemplates.get(aMode)); + + if (templates) { + txListIterator templateIter(templates); + + // Find template with highest priority + MatchableTemplate* templ; + while (!matchTemplate && + (templ = + NS_STATIC_CAST(MatchableTemplate*, templateIter.next()))) { + if (templ->mMatch->matches(aNode, aContext)) { + matchTemplate = templ->mFirstInstruction; + *aImportFrame = frame; +#ifdef PR_LOGGING + match = templ->mMatch; +#endif + } + } + } + } + +#ifdef PR_LOGGING + nsAutoString mode; + if (aMode.mLocalName) { + aMode.mLocalName->ToString(mode); + } + nsAutoString nodeName; + aNode->getNodeName(nodeName); + if (matchTemplate) { + nsAutoString matchAttr; + match->toString(matchAttr); + PR_LOG(txLog::xslt, PR_LOG_DEBUG, + ("MatchTemplate, Pattern %s, Mode %s, Node %s\n", + NS_LossyConvertUCS2toASCII(matchAttr).get(), + NS_LossyConvertUCS2toASCII(mode).get(), + NS_LossyConvertUCS2toASCII(nodeName).get())); + } + else { + PR_LOG(txLog::xslt, PR_LOG_DEBUG, + ("No match, Node %s, Mode %s\n", + NS_LossyConvertUCS2toASCII(nodeName).get(), + NS_LossyConvertUCS2toASCII(mode).get())); + } +#endif + + if (!matchTemplate) { + switch(aNode->getNodeType()) { + case Node::ELEMENT_NODE : + case Node::DOCUMENT_NODE : + matchTemplate = mContainerTemplate; + break; + + case Node::ATTRIBUTE_NODE : + case Node::TEXT_NODE : + case Node::CDATA_SECTION_NODE : + matchTemplate = mCharactersTemplate; + break; + + default: + matchTemplate = mEmptyTemplate; + break; + } + } + + return matchTemplate; +} + +txDecimalFormat* +txStylesheet::getDecimalFormat(const txExpandedName& aName) +{ + return NS_STATIC_CAST(txDecimalFormat*, mDecimalFormats.get(aName)); +} + +txInstruction* +txStylesheet::getAttributeSet(const txExpandedName& aName) +{ + return NS_STATIC_CAST(txInstruction*, mAttributeSets.get(aName)); +} + +txInstruction* +txStylesheet::getNamedTemplate(const txExpandedName& aName) +{ + return NS_STATIC_CAST(txInstruction*, mNamedTemplates.get(aName)); +} + +txOutputFormat* +txStylesheet::getOutputFormat() +{ + return &mOutputFormat; +} + +txStylesheet::GlobalVariable* +txStylesheet::getGlobalVariable(const txExpandedName& aName) +{ + return NS_STATIC_CAST(GlobalVariable*, mGlobalVariables.get(aName)); +} + +const txExpandedNameMap& +txStylesheet::getKeyMap() +{ + return mKeys; +} + +PRBool +txStylesheet::isStripSpaceAllowed(Node* aNode, txIMatchContext* aContext) +{ + if (!aNode) { + return MB_FALSE; + } + + switch (aNode->getNodeType()) { + case Node::ELEMENT_NODE: + { + // check Whitespace stipping handling list against given Node + PRInt32 i, frameCount = mStripSpaceTests.Count(); + for (i = 0; i < frameCount; ++i) { + txStripSpaceTest* sst = + NS_STATIC_CAST(txStripSpaceTest*, mStripSpaceTests[i]); + if (sst->matches(aNode, aContext)) { + if (sst->stripsSpace() && + !XMLUtils::getXMLSpacePreserve(aNode)) { + return MB_TRUE; + } + return MB_FALSE; + } + } + break; + } + case Node::TEXT_NODE: + case Node::CDATA_SECTION_NODE: + { + if (!XMLUtils::isWhitespace(aNode)) + return MB_FALSE; + return isStripSpaceAllowed(aNode->getParentNode(), aContext); + } + case Node::DOCUMENT_NODE: + { + return MB_TRUE; + } + } + return MB_FALSE; +} + +nsresult +txStylesheet::doneCompiling() +{ + nsresult rv = NS_OK; + // Collect all importframes into a single ordered list + txListIterator frameIter(&mImportFrames); + rv = frameIter.addAfter(mRootFrame); + NS_ENSURE_SUCCESS(rv, rv); + + mRootFrame = nsnull; + frameIter.next(); + rv = addFrames(frameIter); + NS_ENSURE_SUCCESS(rv, rv); + + // Loop through importframes in decreasing-precedence-order and process + // all items + frameIter.reset(); + ImportFrame* frame; + while ((frame = NS_STATIC_CAST(ImportFrame*, frameIter.next()))) { + nsVoidArray frameStripSpaceTests; + + txListIterator itemIter(&frame->mToplevelItems); + itemIter.resetToEnd(); + txToplevelItem* item; + while ((item = NS_STATIC_CAST(txToplevelItem*, itemIter.previous()))) { + switch (item->getType()) { + case txToplevelItem::attributeSet: + { + rv = addAttributeSet(NS_STATIC_CAST(txAttributeSetItem*, + item)); + NS_ENSURE_SUCCESS(rv, rv); + break; + } + case txToplevelItem::dummy: + case txToplevelItem::import: + { + break; + } + case txToplevelItem::output: + { + mOutputFormat.merge(NS_STATIC_CAST(txOutputItem*, item)->mFormat); + break; + } + case txToplevelItem::stripSpace: + { + rv = addStripSpace(NS_STATIC_CAST(txStripSpaceItem*, item), + frameStripSpaceTests); + NS_ENSURE_SUCCESS(rv, rv); + break; + } + case txToplevelItem::templ: + { + rv = addTemplate(NS_STATIC_CAST(txTemplateItem*, item), + frame); + NS_ENSURE_SUCCESS(rv, rv); + + break; + } + case txToplevelItem::variable: + { + rv = addGlobalVariable(NS_STATIC_CAST(txVariableItem*, + item)); + NS_ENSURE_SUCCESS(rv, rv); + + break; + } + } + delete item; + itemIter.remove(); //remove() moves to the previous + itemIter.next(); + } + if (!mStripSpaceTests.AppendElements(frameStripSpaceTests)) { + return NS_ERROR_OUT_OF_MEMORY; + } + + frameStripSpaceTests.Clear(); + } + + if (!mDecimalFormats.get(txExpandedName())) { + nsAutoPtr format(new txDecimalFormat); + NS_ENSURE_TRUE(format, NS_ERROR_OUT_OF_MEMORY); + + rv = mDecimalFormats.add(txExpandedName(), format); + NS_ENSURE_SUCCESS(rv, rv); + + format.forget(); + } + + return NS_OK; +} + +nsresult +txStylesheet::addTemplate(txTemplateItem* aTemplate, + ImportFrame* aImportFrame) +{ + NS_ASSERTION(aTemplate, "missing template"); + + txInstruction* instr = aTemplate->mFirstInstruction; + nsresult rv = mTemplateInstructions.add(instr); + NS_ENSURE_SUCCESS(rv, rv); + + // mTemplateInstructions now owns the instructions + aTemplate->mFirstInstruction.forget(); + + if (!aTemplate->mName.isNull()) { + rv = mNamedTemplates.add(aTemplate->mName, instr); + NS_ENSURE_TRUE(NS_SUCCEEDED(rv) || rv == NS_ERROR_XSLT_ALREADY_SET, + rv); + } + + if (!aTemplate->mMatch) { + // This is no error, see section 6 Named Templates + + return NS_OK; + } + + // get the txList for the right mode + txList* templates = + NS_STATIC_CAST(txList*, + aImportFrame->mMatchableTemplates.get(aTemplate->mMode)); + + if (!templates) { + nsAutoPtr newList(new txList); + NS_ENSURE_TRUE(newList, NS_ERROR_OUT_OF_MEMORY); + + rv = aImportFrame->mMatchableTemplates.add(aTemplate->mMode, newList); + NS_ENSURE_SUCCESS(rv, rv); + + templates = newList.forget(); + } + + // Add the simple patterns to the list of matchable templates, according + // to default priority + txList simpleMatches; + rv = aTemplate->mMatch->getSimplePatterns(simpleMatches); + if (simpleMatches.get(0) == aTemplate->mMatch) { + aTemplate->mMatch.forget(); + } + + txListIterator simples(&simpleMatches); + while (simples.hasNext()) { + // XXX if we fail in this loop, we leak the remaining simple patterns + nsAutoPtr simple(NS_STATIC_CAST(txPattern*, simples.next())); + double priority = aTemplate->mPrio; + if (Double::isNaN(priority)) { + priority = simple->getDefaultPriority(); + NS_ASSERTION(!Double::isNaN(priority), + "simple pattern without default priority"); + } + nsAutoPtr + nt(new MatchableTemplate(instr, simple, priority)); + NS_ENSURE_TRUE(nt, NS_ERROR_OUT_OF_MEMORY); + + txListIterator templ(templates); + while (templ.hasNext()) { + MatchableTemplate* mt = NS_STATIC_CAST(MatchableTemplate*, + templ.next()); + if (priority > mt->mPriority) { + rv = templ.addBefore(nt); + NS_ENSURE_SUCCESS(rv, rv); + + nt.forget(); + break; + } + } + if (nt) { + rv = templates->add(nt); + NS_ENSURE_SUCCESS(rv, rv); + + nt.forget(); + } + } + + return NS_OK; +} + +nsresult +txStylesheet::addFrames(txListIterator& aInsertIter) +{ + ImportFrame* frame = NS_STATIC_CAST(ImportFrame*, aInsertIter.current()); + nsresult rv = NS_OK; + txListIterator iter(&frame->mToplevelItems); + txToplevelItem* item; + while ((item = NS_STATIC_CAST(txToplevelItem*, iter.next()))) { + if (item->getType() == txToplevelItem::import) { + txImportItem* import = NS_STATIC_CAST(txImportItem*, item); + import->mFrame->mFirstNotImported = + NS_STATIC_CAST(ImportFrame*, aInsertIter.next()); + rv = aInsertIter.addBefore(import->mFrame); + NS_ENSURE_SUCCESS(rv, rv); + + import->mFrame.forget(); + aInsertIter.previous(); + rv = addFrames(aInsertIter); + NS_ENSURE_SUCCESS(rv, rv); + aInsertIter.previous(); + } + } + + return NS_OK; +} + +nsresult +txStylesheet::addStripSpace(txStripSpaceItem* aStripSpaceItem, + nsVoidArray& frameStripSpaceTests) +{ + PRInt32 testCount = aStripSpaceItem->mStripSpaceTests.Count(); + for (; testCount > 0; --testCount) { + txStripSpaceTest* sst = + NS_STATIC_CAST(txStripSpaceTest*, + aStripSpaceItem->mStripSpaceTests[testCount-1]); + double priority = sst->getDefaultPriority(); + PRInt32 i, frameCount = frameStripSpaceTests.Count(); + for (i = 0; i < frameCount; ++i) { + txStripSpaceTest* fsst = + NS_STATIC_CAST(txStripSpaceTest*, frameStripSpaceTests[i]); + if (fsst->getDefaultPriority() < priority) { + break; + } + } + if (!frameStripSpaceTests.InsertElementAt(sst, i)) { + return NS_ERROR_OUT_OF_MEMORY; + } + + aStripSpaceItem->mStripSpaceTests.RemoveElementAt(testCount-1); + } + + return NS_OK; +} + +nsresult +txStylesheet::addAttributeSet(txAttributeSetItem* aAttributeSetItem) +{ + nsresult rv = NS_OK; + txInstruction* oldInstr = + NS_STATIC_CAST(txInstruction*, + mAttributeSets.get(aAttributeSetItem->mName)); + if (!oldInstr) { + rv = mAttributeSets.add(aAttributeSetItem->mName, + aAttributeSetItem->mFirstInstruction); + NS_ENSURE_SUCCESS(rv, rv); + + aAttributeSetItem->mFirstInstruction.forget(); + + return NS_OK; + } + + // We need to prepend the new instructions before the existing ones. + txInstruction* instr = aAttributeSetItem->mFirstInstruction; + txInstruction* lastNonReturn = nsnull; + while (instr->mNext) { + lastNonReturn = instr; + instr = instr->mNext; + } + + if (!lastNonReturn) { + // The new attributeset is empty, so lets just ignore it. + return NS_OK; + } + + rv = mAttributeSets.set(aAttributeSetItem->mName, + aAttributeSetItem->mFirstInstruction); + NS_ENSURE_SUCCESS(rv, rv); + + aAttributeSetItem->mFirstInstruction.forget(); + + delete lastNonReturn->mNext; // Delete the txReturn... + lastNonReturn->mNext = oldInstr; // ...and link up the old instructions. + + return NS_OK; +} + +nsresult +txStylesheet::addGlobalVariable(txVariableItem* aVariable) +{ + if (mGlobalVariables.get(aVariable->mName)) { + return NS_OK; + } + nsAutoPtr var( + new GlobalVariable(aVariable->mValue, aVariable->mFirstInstruction, + aVariable->mIsParam)); + NS_ENSURE_TRUE(var, NS_ERROR_OUT_OF_MEMORY); + + nsresult rv = mGlobalVariables.add(aVariable->mName, var); + NS_ENSURE_SUCCESS(rv, rv); + + var.forget(); + + return NS_OK; + +} + +nsresult +txStylesheet::addKey(const txExpandedName& aName, + nsAutoPtr aMatch, nsAutoPtr aUse) +{ + nsresult rv = NS_OK; + + txXSLKey* xslKey = NS_STATIC_CAST(txXSLKey*, mKeys.get(aName)); + if (!xslKey) { + xslKey = new txXSLKey(aName); + NS_ENSURE_TRUE(xslKey, NS_ERROR_OUT_OF_MEMORY); + + rv = mKeys.add(aName, xslKey); + if (NS_FAILED(rv)) { + delete xslKey; + return rv; + } + } + if (!xslKey->addKey(aMatch, aUse)) { + return NS_ERROR_OUT_OF_MEMORY; + } + return NS_OK; +} + +nsresult +txStylesheet::addDecimalFormat(const txExpandedName& aName, + nsAutoPtr aFormat) +{ + txDecimalFormat* existing = + NS_STATIC_CAST(txDecimalFormat*, mDecimalFormats.get(aName)); + if (existing) { + NS_ENSURE_TRUE(existing->isEqual(aFormat), + NS_ERROR_XSLT_PARSE_FAILURE); + + return NS_OK; + } + + nsresult rv = mDecimalFormats.add(aName, aFormat); + NS_ENSURE_SUCCESS(rv, rv); + + aFormat.forget(); + + return NS_OK; +} + +txStylesheet::ImportFrame::ImportFrame() + : mMatchableTemplates(MB_TRUE), + mFirstNotImported(nsnull) +{ +} + +txStylesheet::ImportFrame::~ImportFrame() +{ + // Delete templates in mMatchableTemplates + txExpandedNameMap::iterator mapIter(mMatchableTemplates); + while (mapIter.next()) { + txListIterator templIter(NS_STATIC_CAST(txList*, mapIter.value())); + MatchableTemplate* templ; + while ((templ = NS_STATIC_CAST(MatchableTemplate*, templIter.next()))) { + delete templ; + } + } + + txListIterator tlIter(&mToplevelItems); + while (tlIter.hasNext()) { + delete NS_STATIC_CAST(txToplevelItem*, tlIter.next()); + } +} + +txStylesheet::GlobalVariable::GlobalVariable(nsAutoPtr aExpr, + nsAutoPtr aFirstInstruction, + PRBool aIsParam) + : mExpr(aExpr), mFirstInstruction(aFirstInstruction), mIsParam(aIsParam) +{ +} diff --git a/mozilla/extensions/transformiix/source/xslt/txStylesheet.h b/mozilla/extensions/transformiix/source/xslt/txStylesheet.h new file mode 100644 index 00000000000..fddef11a017 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/txStylesheet.h @@ -0,0 +1,248 @@ +/* -*- 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 + * Jonas Sicking. + * Portions created by the Initial Developer are Copyright (C) 2002 + * Jonas Sicking. All Rights Reserved. + * + * Contributor(s): + * Jonas Sicking + * + * 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 TX_TXSTYLESHEET_H +#define TX_TXSTYLESHEET_H + +#include "txOutputFormat.h" +#include "txExpandedNameMap.h" +#include "List.h" +#include "Expr.h" +#include "txXSLTPatterns.h" +#include "txInstructions.h" +#include "XSLTFunctions.h" + +class txInstruction; +class txToplevelItem; +class txTemplateItem; +class txVariableItem; +class txStripSpaceItem; +class txAttributeSetItem; + +class txStylesheet +{ +public: + class ImportFrame; + class GlobalVariable; + friend class txStylesheetCompilerState; + // To be able to do some cleaning up in destructor + friend class ImportFrame; + + txStylesheet(); + ~txStylesheet(); + nsresult init(); + + nsrefcnt AddRef() + { + return ++mRefCnt; + } + nsrefcnt Release() + { + if (--mRefCnt == 0) { + mRefCnt = 1; //stabilize + delete this; + return 0; + } + return mRefCnt; + } + + txInstruction* findTemplate(Node* aNode, + const txExpandedName& aMode, + txIMatchContext* aContext, + ImportFrame* aImportedBy, + ImportFrame** aImportFrame); + txDecimalFormat* getDecimalFormat(const txExpandedName& aName); + txInstruction* getAttributeSet(const txExpandedName& aName); + txInstruction* getNamedTemplate(const txExpandedName& aName); + txOutputFormat* getOutputFormat(); + GlobalVariable* getGlobalVariable(const txExpandedName& aName); + const txExpandedNameMap& getKeyMap(); + PRBool isStripSpaceAllowed(Node* aNode, txIMatchContext* aContext); + + /** + * Called by the stylesheet compiler once all stylesheets has been read. + */ + nsresult doneCompiling(); + + /** + * Add a key to the stylesheet + */ + nsresult addKey(const txExpandedName& aName, nsAutoPtr aMatch, + nsAutoPtr aUse); + + /** + * Add a decimal-format to the stylesheet + */ + nsresult addDecimalFormat(const txExpandedName& aName, + nsAutoPtr aFormat); + + /** + * Contain information that is import precedence dependant. + */ + class ImportFrame { + public: + ImportFrame(); + ~ImportFrame(); + + // List of toplevel items + txList mToplevelItems; + + // Map of template modes, each item in the map is a txList + // of templates + txExpandedNameMap mMatchableTemplates; + + // ImportFrame which is the first one *not* imported by this frame + ImportFrame* mFirstNotImported; + }; + + class GlobalVariable : public TxObject { + public: + GlobalVariable(nsAutoPtr aExpr, + nsAutoPtr aFirstInstruction, + PRBool aIsParam); + + nsAutoPtr mExpr; + nsAutoPtr mFirstInstruction; + PRBool mIsParam; + }; + +private: + class MatchableTemplate { + public: + MatchableTemplate(txInstruction* aFirstInstruction, + nsAutoPtr aPattern, + double aPriority) + : mFirstInstruction(aFirstInstruction), + mMatch(aPattern), + mPriority(aPriority) + { + } + txInstruction* mFirstInstruction; + nsAutoPtr mMatch; + double mPriority; + }; + + nsresult addTemplate(txTemplateItem* aTemplate, ImportFrame* aImportFrame); + nsresult addGlobalVariable(txVariableItem* aVariable); + nsresult addFrames(txListIterator& aInsertIter); + nsresult addStripSpace(txStripSpaceItem* aStripSpaceItem, + nsVoidArray& frameStripSpaceTests); + nsresult addAttributeSet(txAttributeSetItem* aAttributeSetItem); + + // Refcount + nsAutoRefCnt mRefCnt; + + // List of ImportFrames + txList mImportFrames; + + // output format + txOutputFormat mOutputFormat; + + // List of first instructions of templates. This is the owner of all + // instructions used in templates + txList mTemplateInstructions; + + // Root importframe + ImportFrame* mRootFrame; + + // Named templates + txExpandedNameMap mNamedTemplates; + + // Map with all decimal-formats + txExpandedNameMap mDecimalFormats; + + // Map with all named attribute sets + txExpandedNameMap mAttributeSets; + + // Map with all global variables and parameters + txExpandedNameMap mGlobalVariables; + + // Map with all keys + txExpandedNameMap mKeys; + + // Array of all txStripSpaceTests, sorted in acending order + nsVoidArray mStripSpaceTests; + + // Default templates + nsAutoPtr mContainerTemplate; + nsAutoPtr mCharactersTemplate; + nsAutoPtr mEmptyTemplate; +}; + + +/** + * txStripSpaceTest holds both an txNameTest and a bool for use in + * whitespace stripping. + */ +class txStripSpaceTest { +public: + txStripSpaceTest(nsIAtom* aPrefix, nsIAtom* aLocalName, PRInt32 aNSID, + MBool stripSpace) + : mNameTest(aPrefix, aLocalName, aNSID, Node::ELEMENT_NODE), + mStrips(stripSpace) + { + } + + MBool matches(Node* aNode, txIMatchContext* aContext) { + return mNameTest.matches(aNode, aContext); + } + + MBool stripsSpace() { + return mStrips; + } + + double getDefaultPriority() { + return mNameTest.getDefaultPriority(); + } + +protected: + txNameTest mNameTest; + MBool mStrips; +}; + +/** + * Value of a global parameter + */ +class txIGlobalParameter : public TxObject +{ +public: + virtual nsresult getValue(ExprResult** aValue) = 0; +}; + + +#endif //TX_TXSTYLESHEET_H diff --git a/mozilla/extensions/transformiix/source/xslt/txStylesheetCompileHandlers.cpp b/mozilla/extensions/transformiix/source/xslt/txStylesheetCompileHandlers.cpp new file mode 100644 index 00000000000..d4c6fe73442 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/txStylesheetCompileHandlers.cpp @@ -0,0 +1,2898 @@ +/* -*- 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 + * Jonas Sicking. + * Portions created by the Initial Developer are Copyright (C) 2002 + * Jonas Sicking. All Rights Reserved. + * + * Contributor(s): + * Jonas Sicking + * + * 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 "txStylesheetCompiler.h" +#include "txStylesheetCompileHandlers.h" +#include "txTokenizer.h" +#include "txInstructions.h" +#include "txAtoms.h" +#include "primitives.h" +#include "txStringUtils.h" +#include "txStylesheet.h" +#include "txToplevelItems.h" +#include "txPatternParser.h" +#include "txNamespaceMap.h" +#include "txURIUtils.h" +#include "XSLTFunctions.h" + +txHandlerTable* gTxIgnoreHandler = 0; +txHandlerTable* gTxRootHandler = 0; +txHandlerTable* gTxTopHandler = 0; +txHandlerTable* gTxTemplateHandler = 0; +txHandlerTable* gTxTextHandler = 0; +txHandlerTable* gTxApplyTemplatesHandler = 0; +txHandlerTable* gTxCallTemplateHandler = 0; +txHandlerTable* gTxVariableHandler = 0; +txHandlerTable* gTxForEachHandler = 0; +txHandlerTable* gTxTopVariableHandler = 0; +txHandlerTable* gTxChooseHandler = 0; +txHandlerTable* gTxParamHandler = 0; +txHandlerTable* gTxImportHandler = 0; +txHandlerTable* gTxAttributeSetHandler = 0; +txHandlerTable* gTxFallbackHandler = 0; + +nsresult +txFnStartLRE(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState); +nsresult +txFnEndLRE(txStylesheetCompilerState& aState); + + +#define TX_RETURN_IF_WHITESPACE(_str, _state) \ + do { \ + if (!_state.mElementContext->mPreserveWhitespace && \ + XMLUtils::isWhitespace(PromiseFlatString(_str))) { \ + return NS_OK; \ + } \ + } while(0) + + +nsresult +getStyleAttr(txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + PRInt32 aNamespace, + nsIAtom* aName, + PRBool aRequired, + txStylesheetAttr** aAttr) +{ + PRInt32 i; + for (i = 0; i < aAttrCount; ++i) { + txStylesheetAttr* attr = aAttributes + i; + if (attr->mNamespaceID == aNamespace && + attr->mLocalName == aName) { + *aAttr = attr; + + return NS_OK; + } + } + *aAttr = nsnull; + + if (aRequired) { + // XXX ErrorReport: missing required attribute + return NS_ERROR_XSLT_PARSE_FAILURE; + } + + return NS_OK; +} + +nsresult +parseUseAttrSets(txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + PRBool aInXSLTNS, + txStylesheetCompilerState& aState) +{ + txStylesheetAttr* attr = nsnull; + nsresult rv = getStyleAttr(aAttributes, aAttrCount, + aInXSLTNS ? kNameSpaceID_XSLT + : kNameSpaceID_None, + txXSLTAtoms::useAttributeSets, PR_FALSE, + &attr); + if (!attr) { + return rv; + } + + txTokenizer tok(attr->mValue); + while (tok.hasMoreTokens()) { + txExpandedName name; + rv = name.init(tok.nextToken(), aState.mElementContext->mMappings, + PR_FALSE); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr instr(new txInsertAttrSet(name)); + NS_ENSURE_TRUE(instr, NS_ERROR_OUT_OF_MEMORY); + + rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + } + return NS_OK; +} + +nsresult +getQNameAttr(txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + nsIAtom* aName, + PRBool aRequired, + txStylesheetCompilerState& aState, + txExpandedName& aExpName) +{ + aExpName.reset(); + txStylesheetAttr* attr = nsnull; + nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, + aName, aRequired, &attr); + if (!attr) { + return rv; + } + + rv = aExpName.init(attr->mValue, aState.mElementContext->mMappings, + PR_FALSE); + if (!aRequired && NS_FAILED(rv) && aState.fcp()) { + aExpName.reset(); + rv = NS_OK; + } + + return rv; +} + +nsresult +getExprAttr(txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + nsIAtom* aName, + PRBool aRequired, + txStylesheetCompilerState& aState, + nsAutoPtr& aExpr) +{ + aExpr = nsnull; + txStylesheetAttr* attr = nsnull; + nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, + aName, aRequired, &attr); + if (!attr) { + return rv; + } + + aExpr = ExprParser::createExpr(attr->mValue, &aState); + if (!aExpr && (aRequired || !aState.fcp())) { + // XXX ErrorReport: XPath parse failure + return NS_ERROR_XPATH_PARSE_FAILURE; + } + + return NS_OK; +} + +nsresult +getAVTAttr(txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + nsIAtom* aName, + PRBool aRequired, + txStylesheetCompilerState& aState, + nsAutoPtr& aAVT) +{ + aAVT = nsnull; + txStylesheetAttr* attr = nsnull; + nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, + aName, aRequired, &attr); + if (!attr) { + return rv; + } + + aAVT = ExprParser::createAttributeValueTemplate(attr->mValue, &aState); + if (!aAVT && (aRequired || !aState.fcp())) { + // XXX ErrorReport: XPath parse failure + return NS_ERROR_XPATH_PARSE_FAILURE; + } + + return NS_OK; +} + +nsresult +getPatternAttr(txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + nsIAtom* aName, + PRBool aRequired, + txStylesheetCompilerState& aState, + nsAutoPtr& aPattern) +{ + aPattern = nsnull; + txStylesheetAttr* attr = nsnull; + nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, + aName, aRequired, &attr); + if (!attr) { + return rv; + } + + aPattern = txPatternParser::createPattern(attr->mValue, &aState); + if (!aPattern && (aRequired || !aState.fcp())) { + // XXX ErrorReport: XSLT-Pattern parse failure + return NS_ERROR_XPATH_PARSE_FAILURE; + } + + return NS_OK; +} + +nsresult +getNumberAttr(txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + nsIAtom* aName, + PRBool aRequired, + txStylesheetCompilerState& aState, + double& aNumber) +{ + aNumber = Double::NaN; + txStylesheetAttr* attr = nsnull; + nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, + aName, aRequired, &attr); + if (!attr) { + return rv; + } + + aNumber = Double::toDouble(attr->mValue); + if (Double::isNaN(aNumber) && (aRequired || !aState.fcp())) { + // XXX ErrorReport: number parse failure + return NS_ERROR_XSLT_PARSE_FAILURE; + } + + return NS_OK; +} + +nsresult +getAtomAttr(txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + nsIAtom* aName, + PRBool aRequired, + txStylesheetCompilerState& aState, + nsIAtom** aAtom) +{ + *aAtom = nsnull; + txStylesheetAttr* attr = nsnull; + nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, + aName, aRequired, &attr); + if (!attr) { + return rv; + } + + *aAtom = NS_NewAtom(attr->mValue); + NS_ENSURE_TRUE(*aAtom, NS_ERROR_OUT_OF_MEMORY); + + return NS_OK; +} + +nsresult +getYesNoAttr(txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + nsIAtom* aName, + PRBool aRequired, + txStylesheetCompilerState& aState, + txThreeState& aRes) +{ + aRes = eNotSet; + nsCOMPtr atom; + nsresult rv = getAtomAttr(aAttributes, aAttrCount, aName, aRequired, + aState, getter_AddRefs(atom)); + if (!atom) { + return rv; + } + + if (atom == txXSLTAtoms::yes) { + aRes = eTrue; + } + else if (atom == txXSLTAtoms::no) { + aRes = eFalse; + } + else if (aRequired || !aState.fcp()) { + // XXX ErrorReport: unknown values + return NS_ERROR_XSLT_PARSE_FAILURE; + } + + return NS_OK; +} + +nsresult +getCharAttr(txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + nsIAtom* aName, + PRBool aRequired, + txStylesheetCompilerState& aState, + PRUnichar& aChar) +{ + // Don't reset aChar since it contains the default value + txStylesheetAttr* attr = nsnull; + nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, + aName, aRequired, &attr); + if (!attr) { + return rv; + } + + if (attr->mValue.Length() == 1) { + aChar = attr->mValue.CharAt(0); + } + else if (aRequired || !aState.fcp()) { + // XXX ErrorReport: not a character + return NS_ERROR_XSLT_PARSE_FAILURE; + } + + return NS_OK; +} + + +/** + * Ignore and error handlers + */ +nsresult +txFnTextIgnore(const nsAString& aStr, txStylesheetCompilerState& aState) +{ + return NS_OK; +} + +nsresult +txFnTextError(const nsAString& aStr, txStylesheetCompilerState& aState) +{ + TX_RETURN_IF_WHITESPACE(aStr, aState); + + return NS_ERROR_XSLT_PARSE_FAILURE; +} + +nsresult +txFnStartElementIgnore(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + return NS_OK; +} + +nsresult +txFnEndElementIgnore(txStylesheetCompilerState& aState) +{ + return NS_OK; +} + +nsresult +txFnStartElementSetIgnore(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + return aState.pushHandlerTable(gTxIgnoreHandler); +} + +nsresult +txFnEndElementSetIgnore(txStylesheetCompilerState& aState) +{ + aState.popHandlerTable(); + return NS_OK; +} + +nsresult +txFnStartElementError(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + return NS_ERROR_XSLT_PARSE_FAILURE; +} + +nsresult +txFnEndElementError(txStylesheetCompilerState& aState) +{ + NS_ERROR("txFnEndElementError shouldn't be called"); + return NS_ERROR_XSLT_PARSE_FAILURE; +} + + +/** + * Root handlers + */ +nsresult +txFnStartStylesheet(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + txStylesheetAttr* attr; + nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, + txXSLTAtoms::version, PR_TRUE, &attr); + NS_ENSURE_SUCCESS(rv, rv); + + return aState.pushHandlerTable(gTxImportHandler); +} + +nsresult +txFnEndStylesheet(txStylesheetCompilerState& aState) +{ + aState.popHandlerTable(); + return NS_OK; +} + +nsresult +txFnStartElementContinueTopLevel(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + aState.mHandlerTable = gTxTopHandler; + + return NS_ERROR_XSLT_GET_NEW_HANDLER; +} + +nsresult +txFnStartLREStylesheet(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + txStylesheetAttr* attr; + nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_XSLT, + txXSLTAtoms::version, PR_TRUE, &attr); + NS_ENSURE_SUCCESS(rv, rv); + + txExpandedName nullExpr; + double prio = Double::NaN; + nsAutoPtr match(new txRootPattern(MB_TRUE)); + NS_ENSURE_TRUE(match, NS_ERROR_OUT_OF_MEMORY); + + nsAutoPtr templ(new txTemplateItem(match, nullExpr, + nullExpr, prio)); + NS_ENSURE_TRUE(templ, NS_ERROR_OUT_OF_MEMORY); + + aState.openInstructionContainer(templ); + rv = aState.addToplevelItem(templ); + NS_ENSURE_SUCCESS(rv, rv); + + templ.forget(); + + rv = aState.pushHandlerTable(gTxTemplateHandler); + NS_ENSURE_SUCCESS(rv, rv); + + return txFnStartLRE(aNamespaceID, aLocalName, aPrefix, aAttributes, + aAttrCount, aState); +} + +nsresult +txFnEndLREStylesheet(txStylesheetCompilerState& aState) +{ + nsresult rv = txFnEndLRE(aState); + NS_ENSURE_SUCCESS(rv, rv); + + aState.popHandlerTable(); + + nsAutoPtr instr(new txReturn()); + NS_ENSURE_TRUE(instr, NS_ERROR_OUT_OF_MEMORY); + + rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + aState.closeInstructionContainer(); + + return NS_OK; +} + + +/** + * Top handlers + */ +nsresult +txFnStartOtherTop(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + if (aNamespaceID == kNameSpaceID_None) { + return NS_ERROR_XSLT_PARSE_FAILURE; + } + + return aState.pushHandlerTable(gTxIgnoreHandler); +} + +nsresult +txFnEndOtherTop(txStylesheetCompilerState& aState) +{ + aState.popHandlerTable(); + return NS_OK; +} + + +// xsl:attribute-set +nsresult +txFnStartAttributeSet(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + nsresult rv = NS_OK; + txExpandedName name; + rv = getQNameAttr(aAttributes, aAttrCount, txXSLTAtoms::name, PR_TRUE, + aState, name); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr attrSet(new txAttributeSetItem(name)); + NS_ENSURE_TRUE(attrSet, NS_ERROR_OUT_OF_MEMORY); + + aState.openInstructionContainer(attrSet); + + rv = aState.addToplevelItem(attrSet); + NS_ENSURE_SUCCESS(rv, rv); + + attrSet.forget(); + + rv = parseUseAttrSets(aAttributes, aAttrCount, PR_FALSE, aState); + NS_ENSURE_SUCCESS(rv, rv); + + return aState.pushHandlerTable(gTxAttributeSetHandler); +} + +nsresult +txFnEndAttributeSet(txStylesheetCompilerState& aState) +{ + aState.popHandlerTable(); + + nsAutoPtr instr(new txReturn()); + NS_ENSURE_TRUE(instr, NS_ERROR_OUT_OF_MEMORY); + + nsresult rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + aState.closeInstructionContainer(); + + return NS_OK; +} + + +// xsl:decimal-format +nsresult +txFnStartDecimalFormat(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + nsresult rv = NS_OK; + txExpandedName name; + rv = getQNameAttr(aAttributes, aAttrCount, txXSLTAtoms::name, PR_FALSE, + aState, name); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr format(new txDecimalFormat); + NS_ENSURE_TRUE(format, NS_ERROR_OUT_OF_MEMORY); + + rv = getCharAttr(aAttributes, aAttrCount, txXSLTAtoms::decimalSeparator, + PR_FALSE, aState, format->mDecimalSeparator); + NS_ENSURE_SUCCESS(rv, rv); + + rv = getCharAttr(aAttributes, aAttrCount, txXSLTAtoms::groupingSeparator, + PR_FALSE, aState, format->mGroupingSeparator); + NS_ENSURE_SUCCESS(rv, rv); + + txStylesheetAttr* attr = nsnull; + rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, + txXSLTAtoms::infinity, PR_FALSE, &attr); + NS_ENSURE_SUCCESS(rv, rv); + + if (attr) { + format->mInfinity = attr->mValue; + } + + rv = getCharAttr(aAttributes, aAttrCount, txXSLTAtoms::minusSign, + PR_FALSE, aState, format->mMinusSign); + NS_ENSURE_SUCCESS(rv, rv); + + rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, + txXSLTAtoms::NaN, PR_FALSE, &attr); + NS_ENSURE_SUCCESS(rv, rv); + + if (attr) { + format->mNaN = attr->mValue; + } + + rv = getCharAttr(aAttributes, aAttrCount, txXSLTAtoms::percent, + PR_FALSE, aState, format->mPercent); + NS_ENSURE_SUCCESS(rv, rv); + + rv = getCharAttr(aAttributes, aAttrCount, txXSLTAtoms::perMille, + PR_FALSE, aState, format->mPerMille); + NS_ENSURE_SUCCESS(rv, rv); + + rv = getCharAttr(aAttributes, aAttrCount, txXSLTAtoms::zeroDigit, + PR_FALSE, aState, format->mZeroDigit); + NS_ENSURE_SUCCESS(rv, rv); + + rv = getCharAttr(aAttributes, aAttrCount, txXSLTAtoms::digit, + PR_FALSE, aState, format->mDigit); + NS_ENSURE_SUCCESS(rv, rv); + + rv = getCharAttr(aAttributes, aAttrCount, txXSLTAtoms::patternSeparator, + PR_FALSE, aState, format->mPatternSeparator); + NS_ENSURE_SUCCESS(rv, rv); + + rv = aState.mStylesheet->addDecimalFormat(name, format); + NS_ENSURE_SUCCESS(rv, rv); + + return aState.pushHandlerTable(gTxIgnoreHandler); +} + +nsresult +txFnEndDecimalFormat(txStylesheetCompilerState& aState) +{ + aState.popHandlerTable(); + + return NS_OK; +} + +// xsl:import +nsresult +txFnStartImport(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + nsAutoPtr import(new txImportItem); + NS_ENSURE_TRUE(import, NS_ERROR_OUT_OF_MEMORY); + + import->mFrame = new txStylesheet::ImportFrame; + NS_ENSURE_TRUE(import->mFrame, NS_ERROR_OUT_OF_MEMORY); + + nsresult rv = aState.addToplevelItem(import); + NS_ENSURE_SUCCESS(rv, rv); + + txImportItem* importPtr = import.forget(); + + txStylesheetAttr* attr = nsnull; + rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, + txXSLTAtoms::href, PR_TRUE, &attr); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoString absUri; + URIUtils::resolveHref(attr->mValue, aState.mElementContext->mBaseURI, + absUri); + rv = aState.loadImportedStylesheet(absUri, importPtr->mFrame); + NS_ENSURE_SUCCESS(rv, rv); + + return aState.pushHandlerTable(gTxIgnoreHandler); +} + +nsresult +txFnEndImport(txStylesheetCompilerState& aState) +{ + aState.popHandlerTable(); + + return NS_OK; +} + +// xsl:include +nsresult +txFnStartInclude(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + txStylesheetAttr* attr = nsnull; + nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, + txXSLTAtoms::href, PR_TRUE, &attr); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoString absUri; + URIUtils::resolveHref(attr->mValue, aState.mElementContext->mBaseURI, + absUri); + rv = aState.loadIncludedStylesheet(absUri); + NS_ENSURE_SUCCESS(rv, rv); + + return aState.pushHandlerTable(gTxIgnoreHandler); +} + +nsresult +txFnEndInclude(txStylesheetCompilerState& aState) +{ + aState.popHandlerTable(); + + return NS_OK; +} + +// xsl:key +nsresult +txFnStartKey(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + nsresult rv = NS_OK; + txExpandedName name; + rv = getQNameAttr(aAttributes, aAttrCount, txXSLTAtoms::name, PR_TRUE, + aState, name); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr match; + rv = getPatternAttr(aAttributes, aAttrCount, txXSLTAtoms::match, PR_TRUE, + aState, match); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr use; + rv = getExprAttr(aAttributes, aAttrCount, txXSLTAtoms::use, PR_TRUE, + aState, use); + NS_ENSURE_SUCCESS(rv, rv); + + rv = aState.mStylesheet->addKey(name, match, use); + NS_ENSURE_SUCCESS(rv, rv); + + return aState.pushHandlerTable(gTxIgnoreHandler); +} + +nsresult +txFnEndKey(txStylesheetCompilerState& aState) +{ + aState.popHandlerTable(); + + return NS_OK; +} + +// xsl:output +nsresult +txFnStartOutput(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + nsresult rv = NS_OK; + + nsAutoPtr item(new txOutputItem); + NS_ENSURE_TRUE(item, NS_ERROR_OUT_OF_MEMORY); + + txExpandedName methodExpName; + rv = getQNameAttr(aAttributes, aAttrCount, txXSLTAtoms::method, PR_FALSE, + aState, methodExpName); + NS_ENSURE_SUCCESS(rv, rv); + + if (!methodExpName.isNull()) { + if (methodExpName.mNamespaceID != kNameSpaceID_None) { + // The spec doesn't say what to do here so we'll just ignore the + // value. We could possibly warn. + } + else if (methodExpName.mLocalName == txXSLTAtoms::html) { + item->mFormat.mMethod = eHTMLOutput; + } + else if (methodExpName.mLocalName == txXSLTAtoms::text) { + item->mFormat.mMethod = eTextOutput; + } + else if (methodExpName.mLocalName == txXSLTAtoms::xml) { + item->mFormat.mMethod = eXMLOutput; + } + else { + return NS_ERROR_XSLT_PARSE_FAILURE; + } + } + + txStylesheetAttr* attr = nsnull; + getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, + txXSLTAtoms::version, PR_FALSE, &attr); + if (attr) { + item->mFormat.mVersion = attr->mValue; + } + + getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, + txXSLTAtoms::encoding, PR_FALSE, &attr); + if (attr) { + item->mFormat.mEncoding = attr->mValue; + } + + rv = getYesNoAttr(aAttributes, aAttrCount, + txXSLTAtoms::omitXmlDeclaration, PR_FALSE, aState, + item->mFormat.mOmitXMLDeclaration); + NS_ENSURE_SUCCESS(rv, rv); + + rv = getYesNoAttr(aAttributes, aAttrCount, + txXSLTAtoms::standalone, PR_FALSE, aState, + item->mFormat.mStandalone); + NS_ENSURE_SUCCESS(rv, rv); + + getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, + txXSLTAtoms::doctypePublic, PR_FALSE, &attr); + if (attr) { + item->mFormat.mPublicId = attr->mValue; + } + + getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, + txXSLTAtoms::doctypeSystem, PR_FALSE, &attr); + if (attr) { + item->mFormat.mSystemId = attr->mValue; + } + + getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, + txXSLTAtoms::cdataSectionElements, PR_FALSE, &attr); + if (attr) { + txTokenizer tokens(attr->mValue); + while (tokens.hasMoreTokens()) { + txExpandedName* qname = new txExpandedName(); + NS_ENSURE_TRUE(qname, NS_ERROR_OUT_OF_MEMORY); + + rv = qname->init(tokens.nextToken(), + aState.mElementContext->mMappings, PR_FALSE); + NS_ENSURE_SUCCESS(rv, rv); + + rv = item->mFormat.mCDATASectionElements.add(qname); + NS_ENSURE_SUCCESS(rv, rv); + } + } + + rv = getYesNoAttr(aAttributes, aAttrCount, + txXSLTAtoms::indent, PR_FALSE, aState, + item->mFormat.mIndent); + NS_ENSURE_SUCCESS(rv, rv); + + getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, + txXSLTAtoms::mediaType, PR_FALSE, &attr); + if (attr) { + item->mFormat.mMediaType = attr->mValue; + } + + rv = aState.addToplevelItem(item); + NS_ENSURE_SUCCESS(rv, rv); + + item.forget(); + + return aState.pushHandlerTable(gTxIgnoreHandler); +} + +nsresult +txFnEndOutput(txStylesheetCompilerState& aState) +{ + aState.popHandlerTable(); + + return NS_OK; +} + +// xsl:strip-space/xsl:preserve-space +nsresult +txFnStartStripSpace(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + txStylesheetAttr* attr = nsnull; + nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, + txXSLTAtoms::elements, PR_TRUE, &attr); + NS_ENSURE_SUCCESS(rv, rv); + + PRBool strip = aLocalName == txXSLTAtoms::stripSpace; + + nsAutoPtr stripItem(new txStripSpaceItem); + NS_ENSURE_TRUE(stripItem, NS_ERROR_OUT_OF_MEMORY); + + txTokenizer tokenizer(attr->mValue); + while (tokenizer.hasMoreTokens()) { + const nsASingleFragmentString& name = tokenizer.nextToken(); + PRInt32 ns = kNameSpaceID_None; + nsCOMPtr prefix, localName; + rv = XMLUtils::splitXMLName(name, getter_AddRefs(prefix), + getter_AddRefs(localName)); + if (NS_FAILED(rv)) { + // check for "*" or "prefix:*" + PRUint32 length = name.Length(); + const PRUnichar* c; + name.BeginReading(c); + if (length == 2 || c[length-1] != '*') { + // these can't work + return NS_ERROR_XSLT_PARSE_FAILURE; + } + if (length > 1) { + // Check for a valid prefix, that is, the returned prefix + // should be empty and the real prefix is returned in + // localName. + if (c[length-2] != ':') { + return NS_ERROR_XSLT_PARSE_FAILURE; + } + rv = XMLUtils::splitXMLName(Substring(name, 0, length-2), + getter_AddRefs(prefix), + getter_AddRefs(localName)); + if (NS_FAILED(rv) || prefix) { + // bad chars or two ':' + return NS_ERROR_XSLT_PARSE_FAILURE; + } + prefix = localName; + } + localName = txXPathAtoms::_asterix; + } + if (prefix) { + ns = aState.mElementContext->mMappings->lookupNamespace(prefix); + NS_ENSURE_TRUE(ns != kNameSpaceID_Unknown, NS_ERROR_FAILURE); + } + nsAutoPtr sst(new txStripSpaceTest(prefix, localName, + ns, strip)); + NS_ENSURE_TRUE(sst, NS_ERROR_OUT_OF_MEMORY); + + rv = stripItem->addStripSpaceTest(sst); + NS_ENSURE_SUCCESS(rv, rv); + + sst.forget(); + } + + rv = aState.addToplevelItem(stripItem); + NS_ENSURE_SUCCESS(rv, rv); + + stripItem.forget(); + + return aState.pushHandlerTable(gTxIgnoreHandler); +} + +nsresult +txFnEndStripSpace(txStylesheetCompilerState& aState) +{ + aState.popHandlerTable(); + + return NS_OK; +} + +// xsl:template +nsresult +txFnStartTemplate(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + nsresult rv = NS_OK; + txExpandedName name; + rv = getQNameAttr(aAttributes, aAttrCount, txXSLTAtoms::name, PR_FALSE, + aState, name); + NS_ENSURE_SUCCESS(rv, rv); + + txExpandedName mode; + rv = getQNameAttr(aAttributes, aAttrCount, txXSLTAtoms::mode, PR_FALSE, + aState, mode); + NS_ENSURE_SUCCESS(rv, rv); + + double prio = Double::NaN; + rv = getNumberAttr(aAttributes, aAttrCount, txXSLTAtoms::priority, + PR_FALSE, aState, prio); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr match; + rv = getPatternAttr(aAttributes, aAttrCount, txXSLTAtoms::match, + name.isNull(), aState, match); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr templ(new txTemplateItem(match, name, mode, prio)); + NS_ENSURE_TRUE(templ, NS_ERROR_OUT_OF_MEMORY); + + aState.openInstructionContainer(templ); + rv = aState.addToplevelItem(templ); + NS_ENSURE_SUCCESS(rv, rv); + + templ.forget(); + + return aState.pushHandlerTable(gTxParamHandler); +} + +nsresult +txFnEndTemplate(txStylesheetCompilerState& aState) +{ + aState.popHandlerTable(); + + nsAutoPtr instr(new txReturn()); + NS_ENSURE_TRUE(instr, NS_ERROR_OUT_OF_MEMORY); + + nsresult rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + aState.closeInstructionContainer(); + + return NS_OK; +} + +// xsl:variable, xsl:param +nsresult +txFnStartTopVariable(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + nsresult rv = NS_OK; + txExpandedName name; + rv = getQNameAttr(aAttributes, aAttrCount, txXSLTAtoms::name, PR_TRUE, + aState, name); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr select; + rv = getExprAttr(aAttributes, aAttrCount, txXSLTAtoms::select, PR_FALSE, + aState, select); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr var( + new txVariableItem(name, select, aLocalName == txXSLTAtoms::param)); + NS_ENSURE_TRUE(var, NS_ERROR_OUT_OF_MEMORY); + + aState.openInstructionContainer(var); + rv = aState.pushPtr(var); + NS_ENSURE_SUCCESS(rv, rv); + + if (var->mValue) { + // XXX should be gTxErrorHandler? + rv = aState.pushHandlerTable(gTxIgnoreHandler); + NS_ENSURE_SUCCESS(rv, rv); + } + else { + rv = aState.pushHandlerTable(gTxTopVariableHandler); + NS_ENSURE_SUCCESS(rv, rv); + } + + rv = aState.addToplevelItem(var); + NS_ENSURE_SUCCESS(rv, rv); + + var.forget(); + + return NS_OK; +} + +nsresult +txFnEndTopVariable(txStylesheetCompilerState& aState) +{ + txHandlerTable* prev = aState.mHandlerTable; + aState.popHandlerTable(); + txVariableItem* var = NS_STATIC_CAST(txVariableItem*, aState.popPtr()); + + if (prev == gTxTopVariableHandler) { + // No children were found. + NS_ASSERTION(!var->mValue, + "There shouldn't be a select-expression here"); + var->mValue = new StringExpr(NS_LITERAL_STRING("")); + NS_ENSURE_TRUE(var->mValue, NS_ERROR_OUT_OF_MEMORY); + } + else if (!var->mValue) { + // If we don't have a select-expression there mush be children. + nsAutoPtr instr(new txReturn()); + NS_ENSURE_TRUE(instr, NS_ERROR_OUT_OF_MEMORY); + + nsresult rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + } + + aState.closeInstructionContainer(); + + return NS_OK; +} + +nsresult +txFnStartElementStartTopVar(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + aState.mHandlerTable = gTxTemplateHandler; + + return NS_ERROR_XSLT_GET_NEW_HANDLER; +} + +nsresult +txFnTextStartTopVar(const nsAString& aStr, txStylesheetCompilerState& aState) +{ + TX_RETURN_IF_WHITESPACE(aStr, aState); + + aState.mHandlerTable = gTxTemplateHandler; + + return NS_ERROR_XSLT_GET_NEW_HANDLER; +} + +/** + * Template Handlers + */ + +/* + LRE + + txStartLREElement + txInsertAttrSet one for each qname in xsl:use-attribute-sets + txLREAttribute one for each attribute + [children] + txEndElement +*/ +nsresult +txFnStartLRE(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + nsresult rv = NS_OK; + + nsAutoPtr instr(new txStartLREElement(aNamespaceID, + aLocalName, aPrefix)); + NS_ENSURE_TRUE(instr, NS_ERROR_OUT_OF_MEMORY); + + rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + rv = parseUseAttrSets(aAttributes, aAttrCount, PR_TRUE, aState); + NS_ENSURE_SUCCESS(rv, rv); + + txStylesheetAttr* attr = nsnull; + PRInt32 i; + for (i = 0; i < aAttrCount; ++i) { + attr = aAttributes + i; + + if (attr->mNamespaceID == kNameSpaceID_XSLT) { + continue; + } + + nsAutoPtr avt( + ExprParser::createAttributeValueTemplate(attr->mValue, &aState)); + NS_ENSURE_TRUE(avt, NS_ERROR_XPATH_PARSE_FAILURE); + + instr = new txLREAttribute(attr->mNamespaceID, attr->mLocalName, + attr->mPrefix, avt); + NS_ENSURE_TRUE(instr, NS_ERROR_OUT_OF_MEMORY); + + rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + } + + return NS_OK; +} + +nsresult +txFnEndLRE(txStylesheetCompilerState& aState) +{ + nsAutoPtr instr(new txEndElement); + NS_ENSURE_TRUE(instr, NS_ERROR_OUT_OF_MEMORY); + + nsresult rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + +/* + "LRE text" + + txText +*/ +nsresult +txFnText(const nsAString& aStr, txStylesheetCompilerState& aState) +{ + TX_RETURN_IF_WHITESPACE(aStr, aState); + + nsAutoPtr instr(new txText(aStr, MB_FALSE)); + NS_ENSURE_TRUE(instr, NS_ERROR_OUT_OF_MEMORY); + + nsresult rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + +/* + xsl:apply-imports + + txApplyImportsStart + txApplyImportsEnd +*/ +nsresult +txFnStartApplyImports(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + nsresult rv = NS_OK; + + nsAutoPtr instr(new txApplyImportsStart); + NS_ENSURE_TRUE(instr, NS_ERROR_OUT_OF_MEMORY); + + rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + instr = new txApplyImportsEnd; + NS_ENSURE_TRUE(instr, NS_ERROR_OUT_OF_MEMORY); + + rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + return aState.pushHandlerTable(gTxIgnoreHandler); +} + +nsresult +txFnEndApplyImports(txStylesheetCompilerState& aState) +{ + aState.popHandlerTable(); + + return NS_OK; +} + +/* + xsl:apply-templates + + txPushParams + [params] + txPushNewContext -+ (holds s) + txApplyTemplate <-+ | + txLoopNodeSet -+ | + txPopParams <-+ +*/ +nsresult +txFnStartApplyTemplates(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + nsresult rv = NS_OK; + + nsAutoPtr instr(new txPushParams); + NS_ENSURE_TRUE(instr, NS_ERROR_OUT_OF_MEMORY); + + rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + txExpandedName mode; + rv = getQNameAttr(aAttributes, aAttrCount, txXSLTAtoms::mode, PR_FALSE, + aState, mode); + NS_ENSURE_SUCCESS(rv, rv); + + instr = new txApplyTemplates(mode); + NS_ENSURE_TRUE(instr, NS_ERROR_OUT_OF_MEMORY); + + rv = aState.pushObject(instr); + NS_ENSURE_SUCCESS(rv, rv); + + instr.forget(); + + nsAutoPtr select; + rv = getExprAttr(aAttributes, aAttrCount, txXSLTAtoms::select, PR_FALSE, + aState, select); + NS_ENSURE_SUCCESS(rv, rv); + + if (!select) { + nsAutoPtr nt( + new txNodeTypeTest(txNodeTypeTest::NODE_TYPE)); + NS_ENSURE_TRUE(nt, NS_ERROR_OUT_OF_MEMORY); + + select = new LocationStep(nt, LocationStep::CHILD_AXIS); + NS_ENSURE_TRUE(select, NS_ERROR_OUT_OF_MEMORY); + } + + nsAutoPtr pushcontext(new txPushNewContext(select)); + NS_ENSURE_TRUE(pushcontext, NS_ERROR_OUT_OF_MEMORY); + + rv = aState.pushSorter(pushcontext); + NS_ENSURE_SUCCESS(rv, rv); + + rv = aState.pushObject(pushcontext); + NS_ENSURE_SUCCESS(rv, rv); + + pushcontext.forget(); + + return aState.pushHandlerTable(gTxApplyTemplatesHandler); +} + +nsresult +txFnEndApplyTemplates(txStylesheetCompilerState& aState) +{ + aState.popHandlerTable(); + + txPushNewContext* pushcontext = + NS_STATIC_CAST(txPushNewContext*, aState.popObject()); + nsAutoPtr instr(pushcontext); // txPushNewContext + nsresult rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + aState.popSorter(); + + instr = NS_STATIC_CAST(txInstruction*, aState.popObject()); // txApplyTemplates + nsAutoPtr loop(new txLoopNodeSet(instr)); + NS_ENSURE_TRUE(loop, NS_ERROR_OUT_OF_MEMORY); + + rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + instr = loop.forget(); + rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + instr = new txPopParams; + NS_ENSURE_TRUE(instr, NS_ERROR_OUT_OF_MEMORY); + + pushcontext->mBailTarget = instr; + rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + +/* + xsl:attribute + + txPushStringHandler + [children] + txAttribute +*/ +nsresult +txFnStartAttribute(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + nsresult rv = NS_OK; + + nsAutoPtr instr(new txPushStringHandler(PR_TRUE)); + NS_ENSURE_TRUE(instr, NS_ERROR_OUT_OF_MEMORY); + + rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr name; + rv = getAVTAttr(aAttributes, aAttrCount, txXSLTAtoms::name, PR_TRUE, + aState, name); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr nspace; + rv = getAVTAttr(aAttributes, aAttrCount, txXSLTAtoms::_namespace, PR_FALSE, + aState, nspace); + NS_ENSURE_SUCCESS(rv, rv); + + instr = new txAttribute(name, nspace, aState.mElementContext->mMappings); + NS_ENSURE_TRUE(instr, NS_ERROR_OUT_OF_MEMORY); + + rv = aState.pushObject(instr); + NS_ENSURE_SUCCESS(rv, rv); + + instr.forget(); + + // We need to push the template-handler since the current might be + // the attributeset-handler + return aState.pushHandlerTable(gTxTemplateHandler); +} + +nsresult +txFnEndAttribute(txStylesheetCompilerState& aState) +{ + aState.popHandlerTable(); + nsAutoPtr instr(NS_STATIC_CAST(txInstruction*, + aState.popObject())); + nsresult rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + +/* + xsl:call-template + + txPushParams + [params] + txCallTemplate + txPopParams +*/ +nsresult +txFnStartCallTemplate(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + nsresult rv = NS_OK; + + nsAutoPtr instr(new txPushParams); + NS_ENSURE_TRUE(instr, NS_ERROR_OUT_OF_MEMORY); + + rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + txExpandedName name; + rv = getQNameAttr(aAttributes, aAttrCount, txXSLTAtoms::name, PR_TRUE, + aState, name); + NS_ENSURE_SUCCESS(rv, rv); + + instr = new txCallTemplate(name); + NS_ENSURE_TRUE(instr, NS_ERROR_OUT_OF_MEMORY); + + rv = aState.pushObject(instr); + NS_ENSURE_SUCCESS(rv, rv); + + instr.forget(); + + return aState.pushHandlerTable(gTxCallTemplateHandler); +} + +nsresult +txFnEndCallTemplate(txStylesheetCompilerState& aState) +{ + aState.popHandlerTable(); + + // txCallTemplate + nsAutoPtr instr(NS_STATIC_CAST(txInstruction*, + aState.popObject())); + nsresult rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + instr = new txPopParams; + NS_ENSURE_TRUE(instr, NS_ERROR_OUT_OF_MEMORY); + + rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + +/* + xsl:choose + + txCondotionalGoto --+ \ + [children] | | one for each xsl:when + txGoTo --+ | / + | | + txCondotionalGoto | <-+ --+ + [children] | | + txGoTo --+ | + | | + [children] | <-+ for the xsl:otherwise, if there is one + <-+ +*/ +nsresult +txFnStartChoose(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + nsresult rv = aState.pushChooseGotoList(); + NS_ENSURE_SUCCESS(rv, rv); + + return aState.pushHandlerTable(gTxChooseHandler); +} + +nsresult +txFnEndChoose(txStylesheetCompilerState& aState) +{ + nsresult rv = NS_OK; + aState.popHandlerTable(); + txListIterator iter(aState.mChooseGotoList); + txGoTo* gotoinstr; + while ((gotoinstr = NS_STATIC_CAST(txGoTo*, iter.next()))) { + rv = aState.addGotoTarget(&gotoinstr->mTarget); + NS_ENSURE_SUCCESS(rv, rv); + } + + aState.popChooseGotoList(); + + return NS_OK; +} + +/* + xsl:comment + + txPushStringHandler + [children] + txComment +*/ +nsresult +txFnStartComment(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + nsAutoPtr instr(new txPushStringHandler(PR_TRUE)); + NS_ENSURE_TRUE(instr, NS_ERROR_OUT_OF_MEMORY); + + nsresult rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + +nsresult +txFnEndComment(txStylesheetCompilerState& aState) +{ + nsAutoPtr instr(new txComment); + NS_ENSURE_TRUE(instr, NS_ERROR_OUT_OF_MEMORY); + + nsresult rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + +/* + xsl:copy + + txCopy -+ + txInsertAttrSet | one for each qname in use-attribute-sets + [children] | + txEndElement | + <-+ +*/ +nsresult +txFnStartCopy(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + nsAutoPtr copy(new txCopy); + NS_ENSURE_TRUE(copy, NS_ERROR_OUT_OF_MEMORY); + + nsresult rv = aState.pushPtr(copy); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr instr(copy.forget()); + rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + rv = parseUseAttrSets(aAttributes, aAttrCount, PR_FALSE, aState); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + +nsresult +txFnEndCopy(txStylesheetCompilerState& aState) +{ + nsAutoPtr instr(new txEndElement); + NS_ENSURE_TRUE(instr, NS_ERROR_OUT_OF_MEMORY); + + nsresult rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + txCopy* copy = NS_STATIC_CAST(txCopy*, aState.popPtr()); + rv = aState.addGotoTarget(©->mBailTarget); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + +/* + xsl:copy-of + + txCopyOf +*/ +nsresult +txFnStartCopyOf(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + nsresult rv = NS_OK; + + nsAutoPtr select; + rv = getExprAttr(aAttributes, aAttrCount, txXSLTAtoms::select, PR_TRUE, + aState, select); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr instr(new txCopyOf(select)); + NS_ENSURE_TRUE(instr, NS_ERROR_OUT_OF_MEMORY); + + rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + return aState.pushHandlerTable(gTxIgnoreHandler); +} + +nsresult +txFnEndCopyOf(txStylesheetCompilerState& aState) +{ + aState.popHandlerTable(); + return NS_OK; +} + +/* + xsl:element + + txStartElement + txInsertAttrSet one for each qname in use-attribute-sets + [children] + txEndElement +*/ +nsresult +txFnStartElement(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + nsresult rv = NS_OK; + + nsAutoPtr name; + rv = getAVTAttr(aAttributes, aAttrCount, txXSLTAtoms::name, PR_TRUE, + aState, name); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr nspace; + rv = getAVTAttr(aAttributes, aAttrCount, txXSLTAtoms::_namespace, PR_FALSE, + aState, nspace); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr instr( + new txStartElement(name, nspace, aState.mElementContext->mMappings)); + NS_ENSURE_TRUE(instr, NS_ERROR_OUT_OF_MEMORY); + + rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + rv = parseUseAttrSets(aAttributes, aAttrCount, PR_FALSE, aState); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + +nsresult +txFnEndElement(txStylesheetCompilerState& aState) +{ + nsAutoPtr instr(new txEndElement); + NS_ENSURE_TRUE(instr, NS_ERROR_OUT_OF_MEMORY); + + nsresult rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + +/* + xsl:fallback + + [children] +*/ +nsresult +txFnStartFallback(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + aState.mSearchingForFallback = PR_FALSE; + + return aState.pushHandlerTable(gTxTemplateHandler); +} + +nsresult +txFnEndFallback(txStylesheetCompilerState& aState) +{ + aState.popHandlerTable(); + + NS_ASSERTION(!aState.mSearchingForFallback, + "bad nesting of unknown-instruction and fallback handlers"); + return NS_OK; +} + +/* + xsl:for-each + + txPushNewContext -+ (holds s) + txPushNullTemplateRule <-+ | + [children] | | + txLoopNodeSet -+ | + <-+ +*/ +nsresult +txFnStartForEach(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + nsresult rv = NS_OK; + + nsAutoPtr select; + rv = getExprAttr(aAttributes, aAttrCount, txXSLTAtoms::select, PR_TRUE, + aState, select); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr pushcontext(new txPushNewContext(select)); + NS_ENSURE_TRUE(pushcontext, NS_ERROR_OUT_OF_MEMORY); + + rv = aState.pushPtr(pushcontext); + NS_ENSURE_SUCCESS(rv, rv); + + rv = aState.pushSorter(pushcontext); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr instr(pushcontext.forget()); + rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + instr = new txPushNullTemplateRule; + NS_ENSURE_TRUE(instr, NS_ERROR_OUT_OF_MEMORY); + + rv = aState.pushPtr(instr); + NS_ENSURE_SUCCESS(rv, rv); + + rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + return aState.pushHandlerTable(gTxForEachHandler); +} + +nsresult +txFnEndForEach(txStylesheetCompilerState& aState) +{ + aState.popHandlerTable(); + + // This is a txPushNullTemplateRule + txInstruction* pnullrule = + NS_STATIC_CAST(txInstruction*, aState.popPtr()); + + nsAutoPtr instr(new txLoopNodeSet(pnullrule)); + nsresult rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + aState.popSorter(); + txPushNewContext* pushcontext = + NS_STATIC_CAST(txPushNewContext*, aState.popPtr()); + aState.addGotoTarget(&pushcontext->mBailTarget); + + return NS_OK; +} + +nsresult +txFnStartElementContinueTemplate(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + aState.mHandlerTable = gTxTemplateHandler; + + return NS_ERROR_XSLT_GET_NEW_HANDLER; +} + +nsresult +txFnTextContinueTemplate(const nsAString& aStr, + txStylesheetCompilerState& aState) +{ + TX_RETURN_IF_WHITESPACE(aStr, aState); + + aState.mHandlerTable = gTxTemplateHandler; + + return NS_ERROR_XSLT_GET_NEW_HANDLER; +} + +/* + xsl:if + + txConditionalGoto -+ + [children] | + <-+ +*/ +nsresult +txFnStartIf(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + nsresult rv = NS_OK; + + nsAutoPtr test; + rv = getExprAttr(aAttributes, aAttrCount, txXSLTAtoms::test, PR_TRUE, + aState, test); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr condGoto(new txConditionalGoto(test, nsnull)); + NS_ENSURE_TRUE(condGoto, NS_ERROR_OUT_OF_MEMORY); + + rv = aState.pushPtr(condGoto); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr instr(condGoto.forget()); + rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + +nsresult +txFnEndIf(txStylesheetCompilerState& aState) +{ + txConditionalGoto* condGoto = + NS_STATIC_CAST(txConditionalGoto*, aState.popPtr()); + return aState.addGotoTarget(&condGoto->mTarget); +} + +/* + xsl:message + + txPushStringHandler + [children] + txMessage +*/ +nsresult +txFnStartMessage(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + nsAutoPtr instr(new txPushStringHandler(PR_FALSE)); + NS_ENSURE_TRUE(instr, NS_ERROR_OUT_OF_MEMORY); + + nsresult rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + txThreeState term; + rv = getYesNoAttr(aAttributes, aAttrCount, txXSLTAtoms::terminate, + PR_FALSE, aState, term); + NS_ENSURE_SUCCESS(rv, rv); + + instr = new txMessage(term == eTrue); + NS_ENSURE_TRUE(instr, NS_ERROR_OUT_OF_MEMORY); + + rv = aState.pushObject(instr); + NS_ENSURE_SUCCESS(rv, rv); + + instr.forget(); + + return NS_OK; +} + +nsresult +txFnEndMessage(txStylesheetCompilerState& aState) +{ + nsAutoPtr instr(NS_STATIC_CAST(txInstruction*, + aState.popObject())); + nsresult rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + +/* + xsl:number + + txNumber +*/ +nsresult +txFnStartNumber(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + nsresult rv = NS_OK; + + nsCOMPtr levelAtom; + rv = getAtomAttr(aAttributes, aAttrCount, txXSLTAtoms::level, PR_FALSE, + aState, getter_AddRefs(levelAtom)); + NS_ENSURE_SUCCESS(rv, rv); + + txXSLTNumber::LevelType level = txXSLTNumber::eLevelSingle; + if (levelAtom == txXSLTAtoms::multiple) { + level = txXSLTNumber::eLevelMultiple; + } + else if (levelAtom == txXSLTAtoms::any) { + level = txXSLTNumber::eLevelAny; + } + else if (levelAtom && levelAtom != txXSLTAtoms::single && !aState.fcp()) { + return NS_ERROR_XSLT_PARSE_FAILURE; + } + + nsAutoPtr count; + rv = getPatternAttr(aAttributes, aAttrCount, txXSLTAtoms::count, PR_FALSE, + aState, count); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr from; + rv = getPatternAttr(aAttributes, aAttrCount, txXSLTAtoms::from, PR_FALSE, + aState, from); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr value; + rv = getExprAttr(aAttributes, aAttrCount, txXSLTAtoms::value, PR_FALSE, + aState, value); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr format; + rv = getAVTAttr(aAttributes, aAttrCount, txXSLTAtoms::format, PR_FALSE, + aState, format); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr groupingSeparator; + rv = getAVTAttr(aAttributes, aAttrCount, txXSLTAtoms::groupingSeparator, + PR_FALSE, aState, groupingSeparator); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr groupingSize; + rv = getAVTAttr(aAttributes, aAttrCount, txXSLTAtoms::groupingSize, + PR_FALSE, aState, groupingSize); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr instr(new txNumber(level, count, from, value, + format,groupingSeparator, + groupingSize)); + NS_ENSURE_TRUE(instr, NS_ERROR_OUT_OF_MEMORY); + + rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + return aState.pushHandlerTable(gTxIgnoreHandler); +} + +nsresult +txFnEndNumber(txStylesheetCompilerState& aState) +{ + aState.popHandlerTable(); + + return NS_OK; +} + +/* + xsl:otherwise + + (see xsl:choose) +*/ +nsresult +txFnStartOtherwise(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + return aState.pushHandlerTable(gTxTemplateHandler); +} + +nsresult +txFnEndOtherwise(txStylesheetCompilerState& aState) +{ + aState.popHandlerTable(); + aState.mHandlerTable = gTxIgnoreHandler; // XXX should be gTxErrorHandler + + return NS_OK; +} + +/* + xsl:param + + txCheckParam --+ + txPushRTFHandler | --- (for RTF-parameters) + [children] | / + txSetVariable | + <-+ +*/ +nsresult +txFnStartParam(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + nsresult rv = NS_OK; + + txExpandedName name; + rv = getQNameAttr(aAttributes, aAttrCount, txXSLTAtoms::name, PR_TRUE, + aState, name); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr checkParam(new txCheckParam(name)); + NS_ENSURE_SUCCESS(rv, rv); + + rv = aState.pushPtr(checkParam); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr instr(checkParam.forget()); + rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr select; + rv = getExprAttr(aAttributes, aAttrCount, txXSLTAtoms::select, PR_FALSE, + aState, select); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr var(new txSetVariable(name, select)); + NS_ENSURE_TRUE(var, NS_ERROR_OUT_OF_MEMORY); + + if (var->mValue) { + // XXX should be gTxErrorHandler? + rv = aState.pushHandlerTable(gTxIgnoreHandler); + NS_ENSURE_SUCCESS(rv, rv); + } + else { + rv = aState.pushHandlerTable(gTxVariableHandler); + NS_ENSURE_SUCCESS(rv, rv); + } + + rv = aState.pushObject(var); + NS_ENSURE_SUCCESS(rv, rv); + + var.forget(); + + return NS_OK; +} + +nsresult +txFnEndParam(txStylesheetCompilerState& aState) +{ + nsAutoPtr var(NS_STATIC_CAST(txSetVariable*, + aState.popObject())); + txHandlerTable* prev = aState.mHandlerTable; + aState.popHandlerTable(); + + if (prev == gTxVariableHandler) { + // No children were found. + NS_ASSERTION(!var->mValue, + "There shouldn't be a select-expression here"); + var->mValue = new StringExpr(NS_LITERAL_STRING("")); + NS_ENSURE_TRUE(var->mValue, NS_ERROR_OUT_OF_MEMORY); + } + + nsresult rv = aState.addVariable(var->mName); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr instr(var.forget()); + rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + txCheckParam* checkParam = NS_STATIC_CAST(txCheckParam*, aState.popPtr()); + aState.addGotoTarget(&checkParam->mBailTarget); + + return NS_OK; +} + +/* + xsl:processing-instruction + + txPushStringHandler + [children] + txProcessingInstruction +*/ +nsresult +txFnStartPI(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + nsAutoPtr instr(new txPushStringHandler(PR_TRUE)); + NS_ENSURE_TRUE(instr, NS_ERROR_OUT_OF_MEMORY); + + nsresult rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr name; + rv = getAVTAttr(aAttributes, aAttrCount, txXSLTAtoms::name, PR_TRUE, + aState, name); + NS_ENSURE_SUCCESS(rv, rv); + + instr = new txProcessingInstruction(name); + NS_ENSURE_TRUE(instr, NS_ERROR_OUT_OF_MEMORY); + + rv = aState.pushObject(instr); + NS_ENSURE_SUCCESS(rv, rv); + + instr.forget(); + + return NS_OK; +} + +nsresult +txFnEndPI(txStylesheetCompilerState& aState) +{ + nsAutoPtr instr(NS_STATIC_CAST(txInstruction*, + aState.popObject())); + nsresult rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + +/* + xsl:sort + + (no instructions) +*/ +nsresult +txFnStartSort(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + nsresult rv = NS_OK; + + nsAutoPtr select; + rv = getExprAttr(aAttributes, aAttrCount, txXSLTAtoms::select, PR_FALSE, + aState, select); + NS_ENSURE_SUCCESS(rv, rv); + + if (!select) { + nsAutoPtr nt( + new txNodeTypeTest(txNodeTypeTest::NODE_TYPE)); + NS_ENSURE_TRUE(nt, NS_ERROR_OUT_OF_MEMORY); + + select = new LocationStep(nt, LocationStep::SELF_AXIS); + NS_ENSURE_TRUE(select, NS_ERROR_OUT_OF_MEMORY); + } + + nsAutoPtr lang; + rv = getAVTAttr(aAttributes, aAttrCount, txXSLTAtoms::lang, PR_FALSE, + aState, lang); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr dataType; + rv = getAVTAttr(aAttributes, aAttrCount, txXSLTAtoms::dataType, PR_FALSE, + aState, dataType); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr order; + rv = getAVTAttr(aAttributes, aAttrCount, txXSLTAtoms::order, PR_FALSE, + aState, order); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr caseOrder; + rv = getAVTAttr(aAttributes, aAttrCount, txXSLTAtoms::caseOrder, PR_FALSE, + aState, caseOrder); + NS_ENSURE_SUCCESS(rv, rv); + + rv = aState.mSorter->addSort(select, lang, dataType, order, caseOrder); + NS_ENSURE_SUCCESS(rv, rv); + + return aState.pushHandlerTable(gTxIgnoreHandler); +} + +nsresult +txFnEndSort(txStylesheetCompilerState& aState) +{ + aState.popHandlerTable(); + + return NS_OK; +} + +/* + xsl:text + + [children] (only txText) +*/ +nsresult +txFnStartText(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + NS_ASSERTION(!aState.mDOE, "nested d-o-e elements should not happen"); + + nsresult rv = NS_OK; + txThreeState doe; + rv = getYesNoAttr(aAttributes, aAttrCount, + txXSLTAtoms::disableOutputEscaping, PR_FALSE, aState, + doe); + NS_ENSURE_SUCCESS(rv, rv); + + aState.mDOE = doe == eTrue; + + return aState.pushHandlerTable(gTxTextHandler); +} + +nsresult +txFnEndText(txStylesheetCompilerState& aState) +{ + aState.mDOE = MB_FALSE; + aState.popHandlerTable(); + return NS_OK; +} + +nsresult +txFnTextText(const nsAString& aStr, txStylesheetCompilerState& aState) +{ + nsAutoPtr instr(new txText(aStr, aState.mDOE)); + NS_ENSURE_TRUE(instr, NS_ERROR_OUT_OF_MEMORY); + + nsresult rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + +/* + xsl:value-of + + txValueOf +*/ +nsresult +txFnStartValueOf(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + nsresult rv = NS_OK; + + txThreeState doe; + rv = getYesNoAttr(aAttributes, aAttrCount, + txXSLTAtoms::disableOutputEscaping, PR_FALSE, aState, + doe); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr select; + rv = getExprAttr(aAttributes, aAttrCount, txXSLTAtoms::select, PR_TRUE, + aState, select); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr instr(new txValueOf(select, doe == eTrue)); + NS_ENSURE_TRUE(instr, NS_ERROR_OUT_OF_MEMORY); + + rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + return aState.pushHandlerTable(gTxIgnoreHandler); +} + +nsresult +txFnEndValueOf(txStylesheetCompilerState& aState) +{ + aState.popHandlerTable(); + return NS_OK; +} + +/* + xsl:variable + + txPushRTFHandler --- (for RTF-parameters) + [children] / + txSetVariable +*/ +nsresult +txFnStartVariable(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + nsresult rv = NS_OK; + + txExpandedName name; + rv = getQNameAttr(aAttributes, aAttrCount, txXSLTAtoms::name, PR_TRUE, + aState, name); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr select; + rv = getExprAttr(aAttributes, aAttrCount, txXSLTAtoms::select, PR_FALSE, + aState, select); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr var(new txSetVariable(name, select)); + NS_ENSURE_TRUE(var, NS_ERROR_OUT_OF_MEMORY); + + if (var->mValue) { + // XXX should be gTxErrorHandler? + rv = aState.pushHandlerTable(gTxIgnoreHandler); + NS_ENSURE_SUCCESS(rv, rv); + } + else { + rv = aState.pushHandlerTable(gTxVariableHandler); + NS_ENSURE_SUCCESS(rv, rv); + } + + rv = aState.pushObject(var); + NS_ENSURE_SUCCESS(rv, rv); + + var.forget(); + + return NS_OK; +} + +nsresult +txFnEndVariable(txStylesheetCompilerState& aState) +{ + nsAutoPtr var(NS_STATIC_CAST(txSetVariable*, + aState.popObject())); + + txHandlerTable* prev = aState.mHandlerTable; + aState.popHandlerTable(); + + if (prev == gTxVariableHandler) { + // No children were found. + NS_ASSERTION(!var->mValue, + "There shouldn't be a select-expression here"); + var->mValue = new StringExpr(NS_LITERAL_STRING("")); + NS_ENSURE_TRUE(var->mValue, NS_ERROR_OUT_OF_MEMORY); + } + + nsresult rv = aState.addVariable(var->mName); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr instr(var.forget()); + rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + +nsresult +txFnStartElementStartRTF(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + nsAutoPtr instr(new txPushRTFHandler); + NS_ENSURE_TRUE(instr, NS_ERROR_OUT_OF_MEMORY); + + nsresult rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + aState.mHandlerTable = gTxTemplateHandler; + + return NS_ERROR_XSLT_GET_NEW_HANDLER; +} + +nsresult +txFnTextStartRTF(const nsAString& aStr, txStylesheetCompilerState& aState) +{ + TX_RETURN_IF_WHITESPACE(aStr, aState); + + nsAutoPtr instr(new txPushRTFHandler); + NS_ENSURE_TRUE(instr, NS_ERROR_OUT_OF_MEMORY); + + nsresult rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + aState.mHandlerTable = gTxTemplateHandler; + + return NS_ERROR_XSLT_GET_NEW_HANDLER; +} + +/* + xsl:when + + (see xsl:choose) +*/ +nsresult +txFnStartWhen(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + nsresult rv = NS_OK; + + nsAutoPtr test; + rv = getExprAttr(aAttributes, aAttrCount, txXSLTAtoms::test, PR_TRUE, + aState, test); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr condGoto(new txConditionalGoto(test, nsnull)); + NS_ENSURE_TRUE(condGoto, NS_ERROR_OUT_OF_MEMORY); + + rv = aState.pushPtr(condGoto); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr instr(condGoto.forget()); + rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + return aState.pushHandlerTable(gTxTemplateHandler); +} + +nsresult +txFnEndWhen(txStylesheetCompilerState& aState) +{ + aState.popHandlerTable(); + nsAutoPtr gotoinstr(new txGoTo(nsnull)); + NS_ENSURE_TRUE(gotoinstr, NS_ERROR_OUT_OF_MEMORY); + + nsresult rv = aState.mChooseGotoList->add(gotoinstr); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr instr(gotoinstr.forget()); + rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + txConditionalGoto* condGoto = + NS_STATIC_CAST(txConditionalGoto*, aState.popPtr()); + rv = aState.addGotoTarget(&condGoto->mTarget); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + +/* + xsl:with-param + + txPushRTFHandler -- for RTF-parameters + [children] / + txSetParam +*/ +nsresult +txFnStartWithParam(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + nsresult rv = NS_OK; + + txExpandedName name; + rv = getQNameAttr(aAttributes, aAttrCount, txXSLTAtoms::name, PR_TRUE, + aState, name); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr select; + rv = getExprAttr(aAttributes, aAttrCount, txXSLTAtoms::select, PR_FALSE, + aState, select); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoPtr var(new txSetParam(name, select)); + NS_ENSURE_TRUE(var, NS_ERROR_OUT_OF_MEMORY); + + if (var->mValue) { + // XXX should be gTxErrorHandler? + rv = aState.pushHandlerTable(gTxIgnoreHandler); + NS_ENSURE_SUCCESS(rv, rv); + } + else { + rv = aState.pushHandlerTable(gTxVariableHandler); + NS_ENSURE_SUCCESS(rv, rv); + } + + rv = aState.pushObject(var); + NS_ENSURE_SUCCESS(rv, rv); + + var.forget(); + + return NS_OK; +} + +nsresult +txFnEndWithParam(txStylesheetCompilerState& aState) +{ + nsAutoPtr var(NS_STATIC_CAST(txSetParam*, aState.popObject())); + txHandlerTable* prev = aState.mHandlerTable; + aState.popHandlerTable(); + + if (prev == gTxVariableHandler) { + // No children were found. + NS_ASSERTION(!var->mValue, + "There shouldn't be a select-expression here"); + var->mValue = new StringExpr(NS_LITERAL_STRING("")); + NS_ENSURE_TRUE(var->mValue, NS_ERROR_OUT_OF_MEMORY); + } + + nsAutoPtr instr(var.forget()); + nsresult rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + +/* + Unknown instruction + + [fallbacks] if one or more xsl:fallbacks are found + or + txErrorInstruction otherwise +*/ +nsresult +txFnStartUnknownInstruction(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState) +{ + NS_ASSERTION(!aState.mSearchingForFallback, + "bad nesting of unknown-instruction and fallback handlers"); + aState.mSearchingForFallback = PR_TRUE; + + return aState.pushHandlerTable(gTxFallbackHandler); +} + +nsresult +txFnEndUnknownInstruction(txStylesheetCompilerState& aState) +{ + aState.popHandlerTable(); + + if (aState.mSearchingForFallback) { + nsAutoPtr instr(new txErrorInstruction()); + NS_ENSURE_TRUE(instr, NS_ERROR_OUT_OF_MEMORY); + + nsresult rv = aState.addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + } + + aState.mSearchingForFallback = PR_FALSE; + + return NS_OK; +} + +/** + * Table Datas + */ + +txHandlerTableData gTxIgnoreTableData = { + // Handlers + { { 0, 0, 0, 0 } }, + // Other + { 0, 0, txFnStartElementIgnore, txFnEndElementIgnore }, + // LRE + { 0, 0, txFnStartElementIgnore, txFnEndElementIgnore }, + // Text + txFnTextIgnore +}; + +txHandlerTableData gTxRootTableData = { + // Handlers + { { kNameSpaceID_XSLT, "stylesheet", txFnStartStylesheet, txFnEndStylesheet }, + { kNameSpaceID_XSLT, "transform", txFnStartStylesheet, txFnEndStylesheet }, + { 0, 0, 0, 0 } }, + // Other + { 0, 0, txFnStartElementError, txFnEndElementError }, + // LRE + { 0, 0, txFnStartLREStylesheet, txFnEndLREStylesheet }, + // Text + txFnTextError +}; + +txHandlerTableData gTxTopTableData = { + // Handlers + { { kNameSpaceID_XSLT, "attribute-set", txFnStartAttributeSet, txFnEndAttributeSet }, + { kNameSpaceID_XSLT, "decimal-format", txFnStartDecimalFormat, txFnEndDecimalFormat }, + { kNameSpaceID_XSLT, "include", txFnStartInclude, txFnEndInclude }, + { kNameSpaceID_XSLT, "key", txFnStartKey, txFnEndKey }, + { kNameSpaceID_XSLT, "output", txFnStartOutput, txFnEndOutput }, + { kNameSpaceID_XSLT, "param", txFnStartTopVariable, txFnEndTopVariable }, + { kNameSpaceID_XSLT, "preserve-space", txFnStartStripSpace, txFnEndStripSpace }, + { kNameSpaceID_XSLT, "strip-space", txFnStartStripSpace, txFnEndStripSpace }, + { kNameSpaceID_XSLT, "template", txFnStartTemplate, txFnEndTemplate }, + { kNameSpaceID_XSLT, "variable", txFnStartTopVariable, txFnEndTopVariable }, + { 0, 0, 0, 0 } }, + // Other + { 0, 0, txFnStartOtherTop, txFnEndOtherTop }, + // LRE + { 0, 0, txFnStartOtherTop, txFnEndOtherTop }, + // Text + txFnTextIgnore +}; + +txHandlerTableData gTxTemplateTableData = { + // Handlers + { { kNameSpaceID_XSLT, "apply-imports", txFnStartApplyImports, txFnEndApplyImports }, + { kNameSpaceID_XSLT, "apply-templates", txFnStartApplyTemplates, txFnEndApplyTemplates }, + { kNameSpaceID_XSLT, "attribute", txFnStartAttribute, txFnEndAttribute }, + { kNameSpaceID_XSLT, "call-template", txFnStartCallTemplate, txFnEndCallTemplate }, + { kNameSpaceID_XSLT, "choose", txFnStartChoose, txFnEndChoose }, + { kNameSpaceID_XSLT, "comment", txFnStartComment, txFnEndComment }, + { kNameSpaceID_XSLT, "copy", txFnStartCopy, txFnEndCopy }, + { kNameSpaceID_XSLT, "copy-of", txFnStartCopyOf, txFnEndCopyOf }, + { kNameSpaceID_XSLT, "element", txFnStartElement, txFnEndElement }, + { kNameSpaceID_XSLT, "fallback", txFnStartElementSetIgnore, txFnEndElementSetIgnore }, + { kNameSpaceID_XSLT, "for-each", txFnStartForEach, txFnEndForEach }, + { kNameSpaceID_XSLT, "if", txFnStartIf, txFnEndIf }, + { kNameSpaceID_XSLT, "message", txFnStartMessage, txFnEndMessage }, + { kNameSpaceID_XSLT, "number", txFnStartNumber, txFnEndNumber }, + { kNameSpaceID_XSLT, "processing-instruction", txFnStartPI, txFnEndPI }, + { kNameSpaceID_XSLT, "text", txFnStartText, txFnEndText }, + { kNameSpaceID_XSLT, "value-of", txFnStartValueOf, txFnEndValueOf }, + { kNameSpaceID_XSLT, "variable", txFnStartVariable, txFnEndVariable }, + { 0, 0, 0, 0 } }, + // Other + { 0, 0, txFnStartUnknownInstruction, txFnEndUnknownInstruction }, + // LRE + { 0, 0, txFnStartLRE, txFnEndLRE }, + // Text + txFnText +}; + +txHandlerTableData gTxTextTableData = { + // Handlers + { { 0, 0, 0, 0 } }, + // Other + { 0, 0, txFnStartElementError, txFnEndElementError }, + // LRE + { 0, 0, txFnStartElementError, txFnEndElementError }, + // Text + txFnTextText +}; + +txHandlerTableData gTxApplyTemplatesTableData = { + // Handlers + { { kNameSpaceID_XSLT, "sort", txFnStartSort, txFnEndSort }, + { kNameSpaceID_XSLT, "with-param", txFnStartWithParam, txFnEndWithParam }, + { 0, 0, 0, 0 } }, + // Other + { 0, 0, txFnStartElementSetIgnore, txFnEndElementSetIgnore }, // should this be error? + // LRE + { 0, 0, txFnStartElementSetIgnore, txFnEndElementSetIgnore }, + // Text + txFnTextIgnore +}; + +txHandlerTableData gTxCallTemplateTableData = { + // Handlers + { { kNameSpaceID_XSLT, "with-param", txFnStartWithParam, txFnEndWithParam }, + { 0, 0, 0, 0 } }, + // Other + { 0, 0, txFnStartElementSetIgnore, txFnEndElementSetIgnore }, // should this be error? + // LRE + { 0, 0, txFnStartElementSetIgnore, txFnEndElementSetIgnore }, + // Text + txFnTextIgnore +}; + +txHandlerTableData gTxVariableTableData = { + // Handlers + { { 0, 0, 0, 0 } }, + // Other + { 0, 0, txFnStartElementStartRTF, 0 }, + // LRE + { 0, 0, txFnStartElementStartRTF, 0 }, + // Text + txFnTextStartRTF +}; + +txHandlerTableData gTxForEachTableData = { + // Handlers + { { kNameSpaceID_XSLT, "sort", txFnStartSort, txFnEndSort }, + { 0, 0, 0, 0 } }, + // Other + { 0, 0, txFnStartElementContinueTemplate, 0 }, + // LRE + { 0, 0, txFnStartElementContinueTemplate, 0 }, + // Text + txFnTextContinueTemplate +}; + +txHandlerTableData gTxTopVariableTableData = { + // Handlers + { { 0, 0, 0, 0 } }, + // Other + { 0, 0, txFnStartElementStartTopVar, 0 }, + // LRE + { 0, 0, txFnStartElementStartTopVar, 0 }, + // Text + txFnTextStartTopVar +}; + +txHandlerTableData gTxChooseTableData = { + // Handlers + { { kNameSpaceID_XSLT, "otherwise", txFnStartOtherwise, txFnEndOtherwise }, + { kNameSpaceID_XSLT, "when", txFnStartWhen, txFnEndWhen }, + { 0, 0, 0, 0 } }, + // Other + { 0, 0, txFnStartElementError, 0 }, + // LRE + { 0, 0, txFnStartElementError, 0 }, + // Text + txFnTextError +}; + +txHandlerTableData gTxParamTableData = { + // Handlers + { { kNameSpaceID_XSLT, "param", txFnStartParam, txFnEndParam }, + { 0, 0, 0, 0 } }, + // Other + { 0, 0, txFnStartElementContinueTemplate, 0 }, + // LRE + { 0, 0, txFnStartElementContinueTemplate, 0 }, + // Text + txFnTextContinueTemplate +}; + +txHandlerTableData gTxImportTableData = { + // Handlers + { { kNameSpaceID_XSLT, "import", txFnStartImport, txFnEndImport }, + { 0, 0, 0, 0 } }, + // Other + { 0, 0, txFnStartElementContinueTopLevel, 0 }, + // LRE + { 0, 0, txFnStartOtherTop, txFnEndOtherTop }, // XXX what should we do here? + // Text + txFnTextIgnore // XXX what should we do here? +}; + +txHandlerTableData gTxAttributeSetTableData = { + // Handlers + { { kNameSpaceID_XSLT, "attribute", txFnStartAttribute, txFnEndAttribute }, + { 0, 0, 0, 0 } }, + // Other + { 0, 0, txFnStartElementError, 0 }, + // LRE + { 0, 0, txFnStartElementError, 0 }, + // Text + txFnTextError +}; + +txHandlerTableData gTxFallbackTableData = { + // Handlers + { { kNameSpaceID_XSLT, "fallback", txFnStartFallback, txFnEndFallback }, + { 0, 0, 0, 0 } }, + // Other + { 0, 0, txFnStartElementSetIgnore, txFnEndElementSetIgnore }, + // LRE + { 0, 0, txFnStartElementSetIgnore, txFnEndElementSetIgnore }, + // Text + txFnTextIgnore +}; + + + +/** + * txHandlerTable + */ +txHandlerTable::txHandlerTable() : mHandlers(MB_FALSE) +{ +} + +nsresult +txHandlerTable::init(txHandlerTableData* aTableData) +{ + nsresult rv = NS_OK; + + mTextHandler = aTableData->mTextHandler; + mLREHandler = &aTableData->mLREHandler; + mOtherHandler = &aTableData->mOtherHandler; + + txElementHandler* handler = aTableData->mHandlers; + while (handler->mLocalName) { + nsCOMPtr nameAtom = do_GetAtom(handler->mLocalName); + txExpandedName name(handler->mNamespaceID, nameAtom); + // XXX this cast is a reinterpret_cast, which is sad + rv = mHandlers.add(name, (TxObject*)handler); + NS_ENSURE_SUCCESS(rv, rv); + + handler++; + } + return NS_OK; +} + +txElementHandler* +txHandlerTable::find(PRInt32 aNamespaceID, nsIAtom* aLocalName) +{ + txExpandedName name(aNamespaceID, aLocalName); + // XXX this cast is a reinterpret_cast, same sad story as in ::init + txElementHandler* handler = (txElementHandler*)mHandlers.get(name); + if (!handler) { + handler = mOtherHandler; + } + return handler; +} + +#define INIT_HANDLER(_name) \ + gTx##_name##Handler = new txHandlerTable(); \ + if (!gTx##_name##Handler) \ + return MB_FALSE; \ + \ + rv = gTx##_name##Handler->init(&gTx##_name##TableData); \ + if (NS_FAILED(rv)) \ + return MB_FALSE + +#define SHUTDOWN_HANDLER(_name) \ + delete gTx##_name##Handler; \ + gTx##_name##Handler = nsnull + +// static +MBool +txHandlerTable::init() +{ + nsresult rv = NS_OK; + + INIT_HANDLER(Root); + INIT_HANDLER(Top); + INIT_HANDLER(Ignore); + INIT_HANDLER(Template); + INIT_HANDLER(Text); + INIT_HANDLER(ApplyTemplates); + INIT_HANDLER(CallTemplate); + INIT_HANDLER(Variable); + INIT_HANDLER(ForEach); + INIT_HANDLER(TopVariable); + INIT_HANDLER(Choose); + INIT_HANDLER(Param); + INIT_HANDLER(Import); + INIT_HANDLER(AttributeSet); + INIT_HANDLER(Fallback); + + return MB_TRUE; +} + +// static +void +txHandlerTable::shutdown() +{ + SHUTDOWN_HANDLER(Root); + SHUTDOWN_HANDLER(Top); + SHUTDOWN_HANDLER(Ignore); + SHUTDOWN_HANDLER(Template); + SHUTDOWN_HANDLER(Text); + SHUTDOWN_HANDLER(ApplyTemplates); + SHUTDOWN_HANDLER(CallTemplate); + SHUTDOWN_HANDLER(Variable); + SHUTDOWN_HANDLER(ForEach); + SHUTDOWN_HANDLER(TopVariable); + SHUTDOWN_HANDLER(Choose); + SHUTDOWN_HANDLER(Param); + SHUTDOWN_HANDLER(Import); + SHUTDOWN_HANDLER(AttributeSet); + SHUTDOWN_HANDLER(Fallback); +} diff --git a/mozilla/extensions/transformiix/source/xslt/txStylesheetCompileHandlers.h b/mozilla/extensions/transformiix/source/xslt/txStylesheetCompileHandlers.h new file mode 100644 index 00000000000..1046f7af0f0 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/txStylesheetCompileHandlers.h @@ -0,0 +1,93 @@ +/* -*- 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 + * Jonas Sicking. + * Portions created by the Initial Developer are Copyright (C) 2002 + * Jonas Sicking. All Rights Reserved. + * + * Contributor(s): + * Jonas Sicking + * + * 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_TXSTYLESHEETCOMPILEHANDLERS_H +#define TRANSFRMX_TXSTYLESHEETCOMPILEHANDLERS_H + +#include "txError.h" +#include "txNamespaceMap.h" +#include "txExpandedNameMap.h" + +struct txStylesheetAttr; +class txStylesheetCompilerState; + +typedef nsresult (*HandleStartFn) (PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount, + txStylesheetCompilerState& aState); +typedef nsresult (*HandleEndFn) (txStylesheetCompilerState& aState); +typedef nsresult (*HandleTextFn) (const nsAString& aStr, + txStylesheetCompilerState& aState); + +struct txElementHandler { + PRInt32 mNamespaceID; + char* mLocalName; + HandleStartFn mStartFunction; + HandleEndFn mEndFunction; +}; + +struct txHandlerTableData { + txElementHandler mHandlers[20]; // XXX find a better solution for this + txElementHandler mOtherHandler; + txElementHandler mLREHandler; + HandleTextFn mTextHandler; +}; + +class txHandlerTable +{ +public: + txHandlerTable(); + nsresult init(txHandlerTableData* aTableData); + txElementHandler* find(PRInt32 aNamespaceID, nsIAtom* aLocalName); + + HandleTextFn mTextHandler; + txElementHandler* mLREHandler; + + static MBool init(); + static void shutdown(); + +private: + txElementHandler* mOtherHandler; + txExpandedNameMap mHandlers; +}; + +extern txHandlerTable* gTxRootHandler; + +#endif //TRANSFRMX_TXSTYLESHEETCOMPILEHANDLERS_H diff --git a/mozilla/extensions/transformiix/source/xslt/txStylesheetCompiler.cpp b/mozilla/extensions/transformiix/source/xslt/txStylesheetCompiler.cpp new file mode 100644 index 00000000000..2f4815b98c1 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/txStylesheetCompiler.cpp @@ -0,0 +1,909 @@ +/* -*- 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 + * Jonas Sicking. + * Portions created by the Initial Developer are Copyright (C) 2002 + * Jonas Sicking. All Rights Reserved. + * + * Contributor(s): + * Jonas Sicking + * + * 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 "txStylesheetCompiler.h" +#include "txStylesheetCompileHandlers.h" +#include "txAtoms.h" +#include "txURIUtils.h" +#include "txTokenizer.h" +#include "txStylesheet.h" +#include "txInstructions.h" +#include "txToplevelItems.h" +#include "ExprParser.h" +#include "txPatternParser.h" +#include "txStringUtils.h" +#include "XSLTFunctions.h" +#include "TxLog.h" + +txStylesheetCompiler::txStylesheetCompiler(const nsAString& aBaseURI, + txACompileObserver* aObserver) + : txStylesheetCompilerState(aObserver) +{ + mStatus = init(aBaseURI, nsnull, nsnull); +} + +txStylesheetCompiler::txStylesheetCompiler(const nsAString& aBaseURI, + txStylesheet* aStylesheet, + txListIterator* aInsertPosition, + txACompileObserver* aObserver) + : txStylesheetCompilerState(aObserver) +{ + mStatus = init(aBaseURI, aStylesheet, aInsertPosition); +} + +nsrefcnt +txStylesheetCompiler::AddRef() +{ + return ++mRefCnt; +} + +nsrefcnt +txStylesheetCompiler::Release() +{ + if (--mRefCnt == 0) { + mRefCnt = 1; //stabilize + delete this; + return 0; + } + return mRefCnt; +} + +nsresult +txStylesheetCompiler::startElement(PRInt32 aNamespaceID, nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount) +{ + if (NS_FAILED(mStatus)) { + return mStatus; + } + + nsresult rv = flushCharacters(); + NS_ENSURE_SUCCESS(rv, rv); + + // look for new namespace mappings + PRBool hasOwnNamespaceMap = PR_FALSE; + PRInt32 i; + for (i = 0; i < aAttrCount; ++i) { + txStylesheetAttr* attr = aAttributes + i; + if (attr->mNamespaceID == kNameSpaceID_XMLNS) { + rv = ensureNewElementContext(); + NS_ENSURE_SUCCESS(rv, rv); + + if (!hasOwnNamespaceMap) { + mElementContext->mMappings = + new txNamespaceMap(*mElementContext->mMappings); + NS_ENSURE_TRUE(mElementContext->mMappings, + NS_ERROR_OUT_OF_MEMORY); + hasOwnNamespaceMap = PR_TRUE; + } + + if (attr->mLocalName == txXMLAtoms::xmlns) { + mElementContext->mMappings->addNamespace(nsnull, attr->mValue); + } + else { + mElementContext->mMappings-> + addNamespace(attr->mLocalName, attr->mValue); + } + } + } + + return startElementInternal(aNamespaceID, aLocalName, aPrefix, + aAttributes, aAttrCount); +} + +nsresult +txStylesheetCompiler::startElement(const PRUnichar *aName, + const PRUnichar **aAttrs, + PRInt32 aAttrCount) +{ + if (NS_FAILED(mStatus)) { + return mStatus; + } + + nsresult rv = flushCharacters(); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoArrayPtr atts; + if (aAttrCount > 0) { + atts = new txStylesheetAttr[aAttrCount]; + NS_ENSURE_TRUE(atts, NS_ERROR_OUT_OF_MEMORY); + } + + PRBool hasOwnNamespaceMap = PR_FALSE; + PRInt32 i; + for (i = 0; i < aAttrCount; ++i) { + rv = XMLUtils::splitXMLName(nsDependentString(aAttrs[i * 2]), + getter_AddRefs(atts[i].mPrefix), + getter_AddRefs(atts[i].mLocalName)); + NS_ENSURE_SUCCESS(rv, rv); + atts[i].mValue.Append(aAttrs[i * 2 + 1]); + + nsCOMPtr prefixToBind; + if (atts[i].mPrefix == txXMLAtoms::xmlns) { + prefixToBind = atts[i].mLocalName; + } + else if (!atts[i].mPrefix && atts[i].mLocalName == txXMLAtoms::xmlns) { + prefixToBind = txXMLAtoms::_empty; + } + + if (prefixToBind) { + rv = ensureNewElementContext(); + NS_ENSURE_SUCCESS(rv, rv); + + if (!hasOwnNamespaceMap) { + mElementContext->mMappings = + new txNamespaceMap(*mElementContext->mMappings); + NS_ENSURE_TRUE(mElementContext->mMappings, + NS_ERROR_OUT_OF_MEMORY); + hasOwnNamespaceMap = PR_TRUE; + } + + rv = mElementContext->mMappings-> + addNamespace(prefixToBind, atts[i].mValue); + NS_ENSURE_SUCCESS(rv, rv); + } + } + + for (i = 0; i < aAttrCount; ++i) { + if (atts[i].mPrefix && atts[i].mPrefix != txXMLAtoms::xmlns) { + atts[i].mNamespaceID = + mElementContext->mMappings->lookupNamespace(atts[i].mPrefix); + NS_ENSURE_TRUE(atts[i].mNamespaceID != kNameSpaceID_Unknown, + NS_ERROR_FAILURE); + } + else if (atts[i].mPrefix == txXMLAtoms::xmlns || + (!atts[i].mPrefix && + atts[i].mLocalName == txXMLAtoms::xmlns)) { + atts[i].mNamespaceID = kNameSpaceID_XMLNS; + } + else { + atts[i].mNamespaceID = kNameSpaceID_None; + } + } + + nsCOMPtr prefix, localname; + rv = XMLUtils::splitXMLName(nsDependentString(aName), + getter_AddRefs(prefix), + getter_AddRefs(localname)); + NS_ENSURE_SUCCESS(rv, rv); + + PRInt32 namespaceID = mElementContext->mMappings->lookupNamespace(prefix); + + NS_ENSURE_TRUE(namespaceID != kNameSpaceID_Unknown, NS_ERROR_FAILURE); + + return startElementInternal(namespaceID, localname, prefix, atts, + aAttrCount); +} + +nsresult +txStylesheetCompiler::startElementInternal(PRInt32 aNamespaceID, + nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount) +{ + nsresult rv = NS_OK; + PRInt32 i; + for (i = mInScopeVariables.Count() - 1; i >= 0; --i) { + ++(NS_STATIC_CAST(txInScopeVariable*, mInScopeVariables[i]))->mLevel; + } + + // Update the elementcontext if we have special attributes + for (i = 0; i < aAttrCount; ++i) { + txStylesheetAttr* attr = aAttributes + i; + + // xml:space + if (attr->mNamespaceID == kNameSpaceID_XML && + attr->mLocalName == txXMLAtoms::space) { + rv = ensureNewElementContext(); + NS_ENSURE_SUCCESS(rv, rv); + + if (TX_StringEqualsAtom(attr->mValue, txXMLAtoms::preserve)) { + mElementContext->mPreserveWhitespace = MB_TRUE; + } + else if (TX_StringEqualsAtom(attr->mValue, txXMLAtoms::_default)) { + mElementContext->mPreserveWhitespace = MB_FALSE; + } + else { + return NS_ERROR_XSLT_PARSE_FAILURE; + } + } + + // xml:base + if (attr->mNamespaceID == kNameSpaceID_XML && + attr->mLocalName == txXMLAtoms::base && + !attr->mValue.IsEmpty()) { + rv = ensureNewElementContext(); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoString uri; + URIUtils::resolveHref(attr->mValue, mElementContext->mBaseURI, uri); + mElementContext->mBaseURI = uri; + } + + // extension-element-prefixes + if ((attr->mNamespaceID == kNameSpaceID_XSLT && + attr->mLocalName == txXSLTAtoms::extensionElementPrefixes && + aNamespaceID != kNameSpaceID_XSLT) || + (attr->mNamespaceID == kNameSpaceID_None && + attr->mLocalName == txXSLTAtoms::extensionElementPrefixes && + aNamespaceID == kNameSpaceID_XSLT && + (aLocalName == txXSLTAtoms::stylesheet || + aLocalName == txXSLTAtoms::transform))) { + rv = ensureNewElementContext(); + NS_ENSURE_SUCCESS(rv, rv); + + txTokenizer tok(attr->mValue); + while (tok.hasMoreTokens()) { + PRInt32 namespaceID = mElementContext->mMappings-> + lookupNamespaceWithDefault(tok.nextToken()); + + if (namespaceID == kNameSpaceID_Unknown) + return NS_ERROR_XSLT_PARSE_FAILURE; + + if (!mElementContext->mInstructionNamespaces. + AppendElement(NS_INT32_TO_PTR(namespaceID))) { + return NS_ERROR_OUT_OF_MEMORY; + } + } + } + + // version + if ((attr->mNamespaceID == kNameSpaceID_XSLT && + attr->mLocalName == txXSLTAtoms::version && + aNamespaceID != kNameSpaceID_XSLT) || + (attr->mNamespaceID == kNameSpaceID_None && + attr->mLocalName == txXSLTAtoms::version && + aNamespaceID == kNameSpaceID_XSLT && + (aLocalName == txXSLTAtoms::stylesheet || + aLocalName == txXSLTAtoms::transform))) { + rv = ensureNewElementContext(); + NS_ENSURE_SUCCESS(rv, rv); + + if (attr->mValue.Equals(NS_LITERAL_STRING("1.0"))) { + mElementContext->mForwardsCompatibleParsing = MB_FALSE; + } + else { + mElementContext->mForwardsCompatibleParsing = MB_TRUE; + } + } + } + + // Find the right elementhandler and execute it + MBool isInstruction = MB_FALSE; + PRInt32 count = mElementContext->mInstructionNamespaces.Count(); + for (i = 0; i < count; ++i) { + if (NS_PTR_TO_INT32(mElementContext->mInstructionNamespaces[i]) == + aNamespaceID) { + isInstruction = MB_TRUE; + break; + } + } + + txElementHandler* handler; + do { + handler = isInstruction ? + mHandlerTable->find(aNamespaceID, aLocalName) : + mHandlerTable->mLREHandler; + + rv = (handler->mStartFunction)(aNamespaceID, aLocalName, aPrefix, + aAttributes, aAttrCount, *this); + } while (rv == NS_ERROR_XSLT_GET_NEW_HANDLER); + + NS_ENSURE_SUCCESS(rv, rv); + + rv = pushPtr(handler); + NS_ENSURE_SUCCESS(rv, rv); + + mElementContext->mDepth++; + + return NS_OK; +} + +nsresult +txStylesheetCompiler::endElement() +{ + if (NS_FAILED(mStatus)) { + return mStatus; + } + + nsresult rv = flushCharacters(); + NS_ENSURE_SUCCESS(rv, rv); + + PRInt32 i; + for (i = mInScopeVariables.Count() - 1; i >= 0; --i) { + txInScopeVariable* var = + NS_STATIC_CAST(txInScopeVariable*, mInScopeVariables[i]); + if (!--(var->mLevel)) { + nsAutoPtr instr(new txRemoveVariable(var->mName)); + NS_ENSURE_TRUE(instr, NS_ERROR_OUT_OF_MEMORY); + + rv = addInstruction(instr); + NS_ENSURE_SUCCESS(rv, rv); + + mInScopeVariables.RemoveElementAt(i); + delete var; + } + } + + txElementHandler* handler = NS_STATIC_CAST(txElementHandler*, popPtr()); + rv = (handler->mEndFunction)(*this); + NS_ENSURE_SUCCESS(rv, rv); + + if (!--mElementContext->mDepth) { + // this will delete the old object + mElementContext = NS_STATIC_CAST(txElementContext*, popObject()); + } + + return NS_OK; +} + +nsresult +txStylesheetCompiler::characters(const nsAString& aStr) +{ + if (NS_FAILED(mStatus)) { + return mStatus; + } + + mCharacters.Append(aStr); + + return NS_OK; +} + +nsresult +txStylesheetCompiler::doneLoading() +{ + if (NS_FAILED(mStatus)) { + return mStatus; + } + + mDoneWithThisStylesheet = PR_TRUE; + + return maybeDoneCompiling(); +} + +void +txStylesheetCompiler::cancel(nsresult aError) +{ + if (NS_SUCCEEDED(mStatus)) { + mStatus = aError; + } + + if (mObserver) { + mObserver->onDoneCompiling(this, mStatus); + // This will ensure that we don't call onDoneCompiling twice. Also + // ensures that we don't keep the observer alive longer then necessary. + mObserver = nsnull; + } +} + +txStylesheet* +txStylesheetCompiler::getStylesheet() +{ + return mStylesheet; +} + +nsresult +txStylesheetCompiler::loadURI(const nsAString& aUri, + txStylesheetCompiler* aCompiler) +{ + return mObserver ? mObserver->loadURI(aUri, aCompiler) : NS_ERROR_FAILURE; +} + +void +txStylesheetCompiler::onDoneCompiling(txStylesheetCompiler* aCompiler, + nsresult aResult) +{ + if (NS_FAILED(aResult)) { + cancel(aResult); + return; + } + + mChildCompilerList.RemoveElement(aCompiler); + + maybeDoneCompiling(); +} + +nsresult +txStylesheetCompiler::flushCharacters() +{ + // Bail if we don't have any characters. The handler will detect + // ignoreable whitespace + if (mCharacters.IsEmpty()) { + return NS_OK; + } + + nsresult rv = NS_OK; + + do { + rv = (mHandlerTable->mTextHandler)(mCharacters, *this); + } while (rv == NS_ERROR_XSLT_GET_NEW_HANDLER); + + NS_ENSURE_SUCCESS(rv, rv); + + mCharacters.Truncate(); + + return NS_OK; +} + +nsresult +txStylesheetCompiler::ensureNewElementContext() +{ + // Do we already have a new context? + if (!mElementContext->mDepth) { + return NS_OK; + } + + nsAutoPtr + context(new txElementContext(*mElementContext)); + NS_ENSURE_TRUE(context, NS_ERROR_OUT_OF_MEMORY); + + nsresult rv = pushObject(mElementContext); + NS_ENSURE_SUCCESS(rv, rv); + + mElementContext.forget(); + mElementContext = context; + + return NS_OK; +} + +nsresult +txStylesheetCompiler::maybeDoneCompiling() +{ + if (!mDoneWithThisStylesheet || mChildCompilerList.Count()) { + return NS_OK; + } + + if (mIsTopCompiler) { + nsresult rv = mStylesheet->doneCompiling(); + if (NS_FAILED(rv)) { + cancel(rv); + return rv; + } + } + + if (mObserver) { + mObserver->onDoneCompiling(this, mStatus); + // This will ensure that we don't call onDoneCompiling twice. Also + // ensures that we don't keep the observer alive longer then necessary. + mObserver = nsnull; + } + + return NS_OK; +} + +/** + * txStylesheetCompilerState + */ + + +txStylesheetCompilerState::txStylesheetCompilerState(txACompileObserver* aObserver) + : mHandlerTable(nsnull), + mSorter(nsnull), + mDOE(PR_FALSE), + mSearchingForFallback(PR_FALSE), + mObserver(aObserver), + mDoneWithThisStylesheet(PR_FALSE), + mNextInstrPtr(nsnull), + mToplevelIterator(nsnull) +{ + // XXX Embedded stylesheets have another handler. Probably + mHandlerTable = gTxRootHandler; + +} + +nsresult +txStylesheetCompilerState::init(const nsAString& aBaseURI, + txStylesheet* aStylesheet, + txListIterator* aInsertPosition) +{ + NS_ASSERTION(!aStylesheet || aInsertPosition, + "must provide insertposition if loading subsheet"); + nsresult rv = NS_OK; + if (aStylesheet) { + mStylesheet = aStylesheet; + mToplevelIterator = *aInsertPosition; + mIsTopCompiler = PR_FALSE; + } + else { + mStylesheet = new txStylesheet; + NS_ENSURE_TRUE(mStylesheet, NS_ERROR_OUT_OF_MEMORY); + + rv = mStylesheet->init(); + NS_ENSURE_SUCCESS(rv, rv); + + mToplevelIterator = + txListIterator(&mStylesheet->mRootFrame->mToplevelItems); + mToplevelIterator.next(); // go to the end of the list + mIsTopCompiler = PR_TRUE; + } + + mElementContext = new txElementContext(aBaseURI); + NS_ENSURE_TRUE(mElementContext && mElementContext->mMappings, + NS_ERROR_OUT_OF_MEMORY); + + // Push the "old" txElementContext + rv = pushObject(0); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + + +txStylesheetCompilerState::~txStylesheetCompilerState() +{ + while (!mObjectStack.isEmpty()) { + delete popObject(); + } + + PRInt32 i; + for (i = mInScopeVariables.Count() - 1; i >= 0; --i) { + delete NS_STATIC_CAST(txInScopeVariable*, mInScopeVariables[i]); + } +} + +nsresult +txStylesheetCompilerState::pushHandlerTable(txHandlerTable* aTable) +{ + nsresult rv = pushPtr(mHandlerTable); + NS_ENSURE_SUCCESS(rv, rv); + + mHandlerTable = aTable; + + return NS_OK; +} + +void +txStylesheetCompilerState::popHandlerTable() +{ + mHandlerTable = NS_STATIC_CAST(txHandlerTable*, popPtr()); +} + +nsresult +txStylesheetCompilerState::pushSorter(txPushNewContext* aSorter) +{ + nsresult rv = pushPtr(mSorter); + NS_ENSURE_SUCCESS(rv, rv); + + mSorter = aSorter; + + return NS_OK; +} + +void +txStylesheetCompilerState::popSorter() +{ + mSorter = NS_STATIC_CAST(txPushNewContext*, popPtr()); +} + +nsresult +txStylesheetCompilerState::pushChooseGotoList() +{ + nsresult rv = pushObject(mChooseGotoList); + NS_ENSURE_SUCCESS(rv, rv); + + mChooseGotoList.forget(); + mChooseGotoList = new txList; + NS_ENSURE_TRUE(mChooseGotoList, NS_ERROR_OUT_OF_MEMORY); + + return NS_OK; +} + +void +txStylesheetCompilerState::popChooseGotoList() +{ + // this will delete the old value + mChooseGotoList = NS_STATIC_CAST(txList*, popObject()); +} + +nsresult +txStylesheetCompilerState::pushObject(TxObject* aObject) +{ + return mObjectStack.push(aObject); +} + +TxObject* +txStylesheetCompilerState::popObject() +{ + return NS_STATIC_CAST(TxObject*, mObjectStack.pop()); +} + +nsresult +txStylesheetCompilerState::pushPtr(void* aPtr) +{ + PR_LOG(txLog::xslt, PR_LOG_DEBUG, ("pushPtr: %d\n", aPtr)); + return mOtherStack.push(aPtr); +} + +void* +txStylesheetCompilerState::popPtr() +{ + void* value = mOtherStack.pop(); + PR_LOG(txLog::xslt, PR_LOG_DEBUG, ("popPtr: %d\n", value)); + return value; +} + +MBool +txStylesheetCompilerState::fcp() +{ + return mElementContext->mForwardsCompatibleParsing; +} + +nsresult +txStylesheetCompilerState::addToplevelItem(txToplevelItem* aItem) +{ + return mToplevelIterator.addBefore(aItem); +} + +nsresult +txStylesheetCompilerState::openInstructionContainer(txInstructionContainer* aContainer) +{ + NS_PRECONDITION(!mNextInstrPtr, "can't nest instruction-containers"); + + mNextInstrPtr = aContainer->mFirstInstruction.StartAssignment(); + return NS_OK; +} + +void +txStylesheetCompilerState::closeInstructionContainer() +{ + NS_ASSERTION(mGotoTargetPointers.Count() == 0, + "GotoTargets still exists, did you forget to add txReturn?"); + mNextInstrPtr = 0; +} + +nsresult +txStylesheetCompilerState::addInstruction(nsAutoPtr aInstruction) +{ + NS_PRECONDITION(mNextInstrPtr, "adding instruction outside container"); + + txInstruction* newInstr = aInstruction; + + *mNextInstrPtr = aInstruction.forget(); + mNextInstrPtr = &newInstr->mNext; + + PRInt32 i, count = mGotoTargetPointers.Count(); + for (i = 0; i < count; ++i) { + *NS_STATIC_CAST(txInstruction**, mGotoTargetPointers[i]) = newInstr; + } + mGotoTargetPointers.Clear(); + + return NS_OK; +} + +nsresult +txStylesheetCompilerState::loadIncludedStylesheet(const nsAString& aURI) +{ + NS_ENSURE_TRUE(mObserver, NS_ERROR_NOT_IMPLEMENTED); + + nsAutoPtr item(new txDummyItem); + NS_ENSURE_TRUE(item, NS_ERROR_OUT_OF_MEMORY); + + nsresult rv = mToplevelIterator.addBefore(item); + NS_ENSURE_SUCCESS(rv, rv); + + item.forget(); + + // step back to the dummy-item + mToplevelIterator.previous(); + + txACompileObserver* observer = NS_STATIC_CAST(txStylesheetCompiler*, this); + + nsRefPtr compiler = + new txStylesheetCompiler(aURI, mStylesheet, &mToplevelIterator, + observer); + NS_ENSURE_TRUE(compiler, NS_ERROR_OUT_OF_MEMORY); + + // step forward before calling the observer in case of syncronous loading + mToplevelIterator.next(); + + if (!mChildCompilerList.AppendElement(compiler)) { + return NS_ERROR_OUT_OF_MEMORY; + } + + rv = mObserver->loadURI(aURI, compiler); + if (NS_FAILED(rv)) { + mChildCompilerList.RemoveElement(compiler); + return rv; + } + + return NS_OK; +} + +nsresult +txStylesheetCompilerState::loadImportedStylesheet(const nsAString& aURI, + txStylesheet::ImportFrame* aFrame) +{ + NS_ENSURE_TRUE(mObserver, NS_ERROR_NOT_IMPLEMENTED); + + txListIterator iter(&aFrame->mToplevelItems); + iter.next(); // go to the end of the list + + txACompileObserver* observer = NS_STATIC_CAST(txStylesheetCompiler*, this); + + nsRefPtr compiler = + new txStylesheetCompiler(aURI, mStylesheet, &iter, observer); + NS_ENSURE_TRUE(compiler, NS_ERROR_OUT_OF_MEMORY); + + if (!mChildCompilerList.AppendElement(compiler)) { + return NS_ERROR_OUT_OF_MEMORY; + } + + nsresult rv = mObserver->loadURI(aURI, compiler); + if (NS_FAILED(rv)) { + mChildCompilerList.RemoveElement(compiler); + return rv; + } + + return NS_OK; +} + +nsresult +txStylesheetCompilerState::addGotoTarget(txInstruction** aTargetPointer) +{ + if (!mGotoTargetPointers.AppendElement(aTargetPointer)) { + return NS_ERROR_OUT_OF_MEMORY; + } + + return NS_OK; +} + +nsresult +txStylesheetCompilerState::addVariable(const txExpandedName& aName) +{ + txInScopeVariable* var = new txInScopeVariable(aName); + NS_ENSURE_TRUE(var, NS_ERROR_OUT_OF_MEMORY); + + if (!mInScopeVariables.AppendElement(var)) { + delete var; + return NS_ERROR_OUT_OF_MEMORY; + } + + return NS_OK; +} + +nsresult +txStylesheetCompilerState::resolveNamespacePrefix(nsIAtom* aPrefix, + PRInt32& aID) +{ + NS_ASSERTION(aPrefix && aPrefix != txXMLAtoms::_empty, + "caller should handle default namespace ''"); + aID = mElementContext->mMappings->lookupNamespace(aPrefix); + return (aID != kNameSpaceID_Unknown) ? NS_OK : NS_ERROR_FAILURE; +} + +nsresult +txStylesheetCompilerState::resolveFunctionCall(nsIAtom* aName, PRInt32 aID, + FunctionCall*& aFunction) +{ + aFunction = nsnull; + + if (aID != kNameSpaceID_None) { + return NS_ERROR_XPATH_UNKNOWN_FUNCTION; + } + if (aName == txXSLTAtoms::document) { + aFunction = new DocumentFunctionCall(mElementContext->mBaseURI); + NS_ENSURE_TRUE(aFunction, NS_ERROR_OUT_OF_MEMORY); + + return NS_OK; + } + if (aName == txXSLTAtoms::key) { + aFunction = new txKeyFunctionCall(mElementContext->mMappings); + NS_ENSURE_TRUE(aFunction, NS_ERROR_OUT_OF_MEMORY); + + return NS_OK; + } + if (aName == txXSLTAtoms::formatNumber) { + aFunction = new txFormatNumberFunctionCall(mStylesheet, + mElementContext->mMappings); + NS_ENSURE_TRUE(aFunction, NS_ERROR_OUT_OF_MEMORY); + + return NS_OK; + } + if (aName == txXSLTAtoms::current) { + aFunction = new CurrentFunctionCall(); + NS_ENSURE_TRUE(aFunction, NS_ERROR_OUT_OF_MEMORY); + + return NS_OK; + } + if (aName == txXSLTAtoms::unparsedEntityUri) { + + return NS_ERROR_NOT_IMPLEMENTED; + } + if (aName == txXSLTAtoms::generateId) { + aFunction = new GenerateIdFunctionCall(); + NS_ENSURE_TRUE(aFunction, NS_ERROR_OUT_OF_MEMORY); + + return NS_OK; + } + if (aName == txXSLTAtoms::systemProperty) { + aFunction = new SystemPropertyFunctionCall(mElementContext->mMappings); + NS_ENSURE_TRUE(aFunction, NS_ERROR_OUT_OF_MEMORY); + + return NS_OK; + } + if (aName == txXSLTAtoms::elementAvailable) { + aFunction = + new ElementAvailableFunctionCall(mElementContext->mMappings); + NS_ENSURE_TRUE(aFunction, NS_ERROR_OUT_OF_MEMORY); + + return NS_OK; + } + if (aName == txXSLTAtoms::functionAvailable) { + aFunction = + new FunctionAvailableFunctionCall(mElementContext->mMappings); + NS_ENSURE_TRUE(aFunction, NS_ERROR_OUT_OF_MEMORY); + + return NS_OK; + } + + return NS_ERROR_XPATH_UNKNOWN_FUNCTION; +} + +PRBool +txStylesheetCompilerState::caseInsensitiveNameTests() +{ + return PR_FALSE; +} + +void +txStylesheetCompilerState::receiveError(const nsAString& aMsg, nsresult aRes) +{ + // XXX implement me +} + +txElementContext::txElementContext(const nsAString& aBaseURI) + : mPreserveWhitespace(PR_FALSE), + mForwardsCompatibleParsing(PR_TRUE), + mBaseURI(aBaseURI), + mMappings(new txNamespaceMap), + mDepth(0) +{ + mInstructionNamespaces.AppendElement(NS_INT32_TO_PTR(kNameSpaceID_XSLT)); +} + +txElementContext::txElementContext(const txElementContext& aOther) + : mPreserveWhitespace(aOther.mPreserveWhitespace), + mForwardsCompatibleParsing(aOther.mForwardsCompatibleParsing), + mBaseURI(aOther.mBaseURI), + mMappings(aOther.mMappings), + mDepth(0) +{ + mInstructionNamespaces = aOther.mInstructionNamespaces; +} diff --git a/mozilla/extensions/transformiix/source/xslt/txStylesheetCompiler.h b/mozilla/extensions/transformiix/source/xslt/txStylesheetCompiler.h new file mode 100644 index 00000000000..2b87897de9c --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/txStylesheetCompiler.h @@ -0,0 +1,228 @@ +/* -*- 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 + * Jonas Sicking. + * Portions created by the Initial Developer are Copyright (C) 2002 + * Jonas Sicking. All Rights Reserved. + * + * Contributor(s): + * Jonas Sicking + * + * 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_TXSTYLESHEETCOMPILER_H +#define TRANSFRMX_TXSTYLESHEETCOMPILER_H + +#include "baseutils.h" +#include "txError.h" +#include "txStack.h" +#include "txXSLTPatterns.h" +#include "Expr.h" +#include "XMLUtils.h" +#include "txIXPathContext.h" +#include "txNamespaceMap.h" +#include "nsAutoPtr.h" +#include "txStylesheet.h" + +class txHandlerTable; +class txElementContext; +class txInstructionContainer; +class txInstruction; +class txToplevelItem; +class txPushNewContext; +class txStylesheetCompiler; + +class txElementContext : public TxObject +{ +public: + txElementContext(const nsAString& aBaseURI); + txElementContext(const txElementContext& aOther); + + PRBool mPreserveWhitespace; + PRBool mForwardsCompatibleParsing; + nsString mBaseURI; + nsRefPtr mMappings; + nsVoidArray mInstructionNamespaces; + PRInt32 mDepth; +}; + +class txACompileObserver +{ +public: + virtual nsrefcnt AddRef() = 0; + virtual nsrefcnt Release() = 0; + + virtual nsresult loadURI(const nsAString& aUri, + txStylesheetCompiler* aCompiler) = 0; + virtual void onDoneCompiling(txStylesheetCompiler* aCompiler, + nsresult aResult) = 0; +}; + +#define TX_DECL_ACOMPILEOBSERVER \ + nsrefcnt AddRef(); \ + nsrefcnt Release(); \ + nsresult loadURI(const nsAString& aUri, txStylesheetCompiler* aCompiler); \ + void onDoneCompiling(txStylesheetCompiler* aCompiler, nsresult aResult) + +class txStylesheetCompilerState : public txIParseContext +{ +public: + txStylesheetCompilerState(txACompileObserver* aObserver); + ~txStylesheetCompilerState(); + + nsresult init(const nsAString& aBaseURI, txStylesheet* aStylesheet, + txListIterator* aInsertPosition); + + // Stack functions + nsresult pushHandlerTable(txHandlerTable* aTable); + void popHandlerTable(); + nsresult pushSorter(txPushNewContext* aSorter); + void popSorter(); + nsresult pushChooseGotoList(); + void popChooseGotoList(); + nsresult pushObject(TxObject* aObject); + TxObject* popObject(); + nsresult pushPtr(void* aPtr); + void* popPtr(); + + // State-checking functions + MBool fcp(); + + // stylesheet functions + nsresult addToplevelItem(txToplevelItem* aItem); + nsresult openInstructionContainer(txInstructionContainer* aContainer); + void closeInstructionContainer(); + nsresult addInstruction(nsAutoPtr aInstruction); + nsresult loadIncludedStylesheet(const nsAString& aURI); + nsresult loadImportedStylesheet(const nsAString& aURI, + txStylesheet::ImportFrame* aFrame); + + // misc + nsresult addGotoTarget(txInstruction** aTargetPointer); + nsresult addVariable(const txExpandedName& aName); + + // txIParseContext + nsresult resolveNamespacePrefix(nsIAtom* aPrefix, PRInt32& aID); + nsresult resolveFunctionCall(nsIAtom* aName, PRInt32 aID, + FunctionCall*& aFunction); + PRBool caseInsensitiveNameTests(); + void receiveError(const nsAString& aMsg, nsresult aRes); + + + nsRefPtr mStylesheet; + txHandlerTable* mHandlerTable; + nsAutoPtr mElementContext; + txPushNewContext* mSorter; + nsAutoPtr mChooseGotoList; + PRPackedBool mDOE; + PRPackedBool mSearchingForFallback; + +protected: + nsRefPtr mObserver; + nsVoidArray mInScopeVariables; + nsVoidArray mChildCompilerList; + PRPackedBool mIsTopCompiler; + PRPackedBool mDoneWithThisStylesheet; + +private: + txStack mObjectStack; + txStack mOtherStack; + txInstruction** mNextInstrPtr; + txListIterator mToplevelIterator; + nsVoidArray mGotoTargetPointers; +}; + +struct txStylesheetAttr +{ + PRInt32 mNamespaceID; + nsCOMPtr mLocalName; + nsCOMPtr mPrefix; + nsString mValue; +}; + +class txStylesheetCompiler : private txStylesheetCompilerState, + public txACompileObserver +{ +public: + txStylesheetCompiler(const nsAString& aBaseURI, + txACompileObserver* aObserver); + txStylesheetCompiler(const nsAString& aBaseURI, + txStylesheet* aStylesheet, + txListIterator* aInsertPosition, + txACompileObserver* aObserver); + virtual nsrefcnt AddRef(); + virtual nsrefcnt Release(); + + nsresult startElement(PRInt32 aNamespaceID, nsIAtom* aLocalName, + nsIAtom* aPrefix, txStylesheetAttr* aAttributes, + PRInt32 aAttrCount); + nsresult startElement(const PRUnichar *aName, + const PRUnichar **aAtts, + PRInt32 aAttrCount); + nsresult endElement(); + nsresult characters(const nsAString& aStr); + nsresult doneLoading(); + + void cancel(nsresult aError); + + txStylesheet* getStylesheet(); + + // txACompileObserver + nsresult loadURI(const nsAString& aUri, txStylesheetCompiler* aCompiler); + void onDoneCompiling(txStylesheetCompiler* aCompiler, nsresult aResult); + +private: + nsresult startElementInternal(PRInt32 aNamespaceID, nsIAtom* aLocalName, + nsIAtom* aPrefix, + txStylesheetAttr* aAttributes, + PRInt32 aAttrCount); + + nsresult flushCharacters(); + nsresult ensureNewElementContext(); + nsresult maybeDoneCompiling(); + + nsAutoRefCnt mRefCnt; + nsString mCharacters; + nsresult mStatus; + +protected: + // This exists soly to supress a warning from nsDerivedSafe + txStylesheetCompiler(); +}; + +class txInScopeVariable { +public: + txInScopeVariable(const txExpandedName& aName) : mName(aName), mLevel(1) + { + } + txExpandedName mName; + PRInt32 mLevel; +}; + +#endif diff --git a/mozilla/extensions/transformiix/source/xslt/txTextHandler.cpp b/mozilla/extensions/transformiix/source/xslt/txTextHandler.cpp index f6b8a1ee521..52c572e3905 100644 --- a/mozilla/extensions/transformiix/source/xslt/txTextHandler.cpp +++ b/mozilla/extensions/transformiix/source/xslt/txTextHandler.cpp @@ -39,9 +39,8 @@ #include "txTextHandler.h" #include "nsAString.h" -txTextHandler::txTextHandler(nsAString& aValue, MBool aOnlyText) : mLevel(0), - mValue(aValue), - mOnlyText(aOnlyText) +txTextHandler::txTextHandler(MBool aOnlyText) : mLevel(0), + mOnlyText(aOnlyText) { } diff --git a/mozilla/extensions/transformiix/source/xslt/txTextHandler.h b/mozilla/extensions/transformiix/source/xslt/txTextHandler.h index 6268f8ab98d..1b84302eafe 100644 --- a/mozilla/extensions/transformiix/source/xslt/txTextHandler.h +++ b/mozilla/extensions/transformiix/source/xslt/txTextHandler.h @@ -40,18 +40,20 @@ #define TRANSFRMX_TEXT_HANDLER_H #include "txXMLEventHandler.h" +#include "nsString.h" class txTextHandler : public txAXMLEventHandler { public: - txTextHandler(nsAString& aValue, MBool aOnlyText); + txTextHandler(MBool aOnlyText); virtual ~txTextHandler(); TX_DECL_TXAXMLEVENTHANDLER + nsString mValue; + private: PRUint32 mLevel; - nsAString& mValue; MBool mOnlyText; }; diff --git a/mozilla/extensions/transformiix/source/xslt/txToplevelItems.cpp b/mozilla/extensions/transformiix/source/xslt/txToplevelItems.cpp new file mode 100644 index 00000000000..e19feb56adf --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/txToplevelItems.cpp @@ -0,0 +1,85 @@ +/* -*- 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 + * Jonas Sicking. + * Portions created by the Initial Developer are Copyright (C) 2002 + * Jonas Sicking. All Rights Reserved. + * + * Contributor(s): + * Jonas Sicking + * + * 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 "txToplevelItems.h" +#include "txStylesheet.h" +#include "txInstructions.h" +#include "txXSLTPatterns.h" + +TX_IMPL_GETTYPE(txAttributeSetItem, txToplevelItem::attributeSet) +TX_IMPL_GETTYPE(txImportItem, txToplevelItem::import) +TX_IMPL_GETTYPE(txOutputItem, txToplevelItem::output) +TX_IMPL_GETTYPE(txDummyItem, txToplevelItem::dummy) + +TX_IMPL_GETTYPE(txStripSpaceItem, txToplevelItem::stripSpace) + +txStripSpaceItem::~txStripSpaceItem() +{ + PRInt32 i, count = mStripSpaceTests.Count(); + for (i = 0; i < count; ++i) { + delete NS_STATIC_CAST(txStripSpaceTest*, mStripSpaceTests[0]); + } +} + +nsresult +txStripSpaceItem::addStripSpaceTest(txStripSpaceTest* aStripSpaceTest) +{ + if (!mStripSpaceTests.AppendElement(aStripSpaceTest)) { + return NS_ERROR_OUT_OF_MEMORY; + } + + return NS_OK; +} + +TX_IMPL_GETTYPE(txTemplateItem, txToplevelItem::templ) + +txTemplateItem::txTemplateItem(nsAutoPtr aMatch, + const txExpandedName& aName, + const txExpandedName& aMode, double aPrio) + : mMatch(aMatch), mName(aName), mMode(aMode), mPrio(aPrio) +{ +} + +TX_IMPL_GETTYPE(txVariableItem, txToplevelItem::variable) + +txVariableItem::txVariableItem(const txExpandedName& aName, + nsAutoPtr aValue, + PRBool aIsParam) + : mName(aName), mValue(aValue), mIsParam(aIsParam) +{ +} diff --git a/mozilla/extensions/transformiix/source/xslt/txToplevelItems.h b/mozilla/extensions/transformiix/source/xslt/txToplevelItems.h new file mode 100644 index 00000000000..a91d7786427 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/txToplevelItems.h @@ -0,0 +1,163 @@ +/* -*- 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 + * Jonas Sicking. + * Portions created by the Initial Developer are Copyright (C) 2002 + * Jonas Sicking. All Rights Reserved. + * + * Contributor(s): + * Jonas Sicking + * + * 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_TXTOPLEVELITEMS_H +#define TRANSFRMX_TXTOPLEVELITEMS_H + +#include "txError.h" +#include "txOutputFormat.h" +#include "XMLUtils.h" +#include "txStylesheet.h" + +class txPattern; +class Expr; +class txInstruction; + +class txToplevelItem +{ +public: + virtual ~txToplevelItem() + { + } + + enum type { + attributeSet, + dummy, + import, + //namespaceAlias, + output, + stripSpace, //also used for preserve-space + templ, + variable + }; + + virtual type getType() = 0; +}; + +#define TX_DECL_TOPLEVELITEM virtual type getType(); +#define TX_IMPL_GETTYPE(_class, _type) \ +txToplevelItem::type \ +_class::getType() { return _type;} + +class txInstructionContainer : public txToplevelItem +{ +public: + nsAutoPtr mFirstInstruction; +}; + +// xsl:attribute-set +class txAttributeSetItem : public txInstructionContainer +{ +public: + txAttributeSetItem(const txExpandedName aName) : mName(aName) + { + } + + TX_DECL_TOPLEVELITEM + + txExpandedName mName; +}; + +// xsl:import +class txImportItem : public txToplevelItem +{ +public: + TX_DECL_TOPLEVELITEM + + nsAutoPtr mFrame; +}; + +// xsl:output +class txOutputItem : public txToplevelItem +{ +public: + TX_DECL_TOPLEVELITEM + + txOutputFormat mFormat; +}; + +// insertionpoint for xsl:include +class txDummyItem : public txToplevelItem +{ +public: + TX_DECL_TOPLEVELITEM +}; + +// xsl:strip-space and xsl:preserve-space +class txStripSpaceItem : public txToplevelItem +{ +public: + virtual ~txStripSpaceItem(); + + TX_DECL_TOPLEVELITEM + + nsresult addStripSpaceTest(txStripSpaceTest* aStripSpaceTest); + + nsVoidArray mStripSpaceTests; +}; + +// xsl:template +class txTemplateItem : public txInstructionContainer +{ +public: + txTemplateItem(nsAutoPtr aMatch, const txExpandedName& aName, + const txExpandedName& aMode, double aPrio); + + TX_DECL_TOPLEVELITEM + + nsAutoPtr mMatch; + txExpandedName mName; + txExpandedName mMode; + double mPrio; +}; + +// xsl:variable at top level +class txVariableItem : public txInstructionContainer +{ +public: + txVariableItem(const txExpandedName& aName, nsAutoPtr aValue, + PRBool aIsParam); + + TX_DECL_TOPLEVELITEM + + txExpandedName mName; + nsAutoPtr mValue; + PRBool mIsParam; +}; + +#endif //TRANSFRMX_TXTOPLEVELITEMS_H diff --git a/mozilla/extensions/transformiix/source/xslt/txUnknownHandler.cpp b/mozilla/extensions/transformiix/source/xslt/txUnknownHandler.cpp index fe66e901ce1..08bc4ed3b22 100644 --- a/mozilla/extensions/transformiix/source/xslt/txUnknownHandler.cpp +++ b/mozilla/extensions/transformiix/source/xslt/txUnknownHandler.cpp @@ -37,11 +37,12 @@ * ***** END LICENSE BLOCK ***** */ #include "txUnknownHandler.h" -#include "ProcessorState.h" +#include "txExecutionState.h" #include "txStringUtils.h" +#include "txStylesheet.h" -txUnknownHandler::txUnknownHandler(ProcessorState* aPs) - : mPs(aPs) +txUnknownHandler::txUnknownHandler(txExecutionState* aEs) + : mEs(aEs) { } @@ -69,7 +70,7 @@ void txUnknownHandler::endDocument() if (NS_FAILED(rv)) return; - mPs->mResultHandler->endDocument(); + mEs->mResultHandler->endDocument(); delete this; } @@ -78,7 +79,7 @@ void txUnknownHandler::startElement(const nsAString& aName, const PRInt32 aNsID) { nsresult rv = NS_OK; - txOutputFormat* format = mPs->getOutputFormat(); + txOutputFormat* format = mEs->mStylesheet->getOutputFormat(); if (format->mMethod != eMethodNotSet) { rv = createHandlerAndFlush(format->mMethod, aName, aNsID); } @@ -93,7 +94,7 @@ void txUnknownHandler::startElement(const nsAString& aName, if (NS_FAILED(rv)) return; - mPs->mResultHandler->startElement(aName, aNsID); + mEs->mResultHandler->startElement(aName, aNsID); delete this; } @@ -104,17 +105,18 @@ nsresult txUnknownHandler::createHandlerAndFlush(txOutputMethod aMethod, { NS_ENSURE_TRUE(mBuffer, NS_ERROR_NOT_INITIALIZED); - txOutputFormat* format = mPs->getOutputFormat(); - format->mMethod = aMethod; + txOutputFormat format; + format.merge(*mEs->mStylesheet->getOutputFormat()); + format.mMethod = aMethod; txAXMLEventHandler* handler = 0; - nsresult rv = mPs->mOutputHandlerFactory->createHandlerWith(format, aName, + nsresult rv = mEs->mOutputHandlerFactory->createHandlerWith(&format, aName, aNsID, &handler); NS_ENSURE_SUCCESS(rv, rv); - mPs->mOutputHandler = handler; - mPs->mResultHandler = handler; + mEs->mOutputHandler = handler; + mEs->mResultHandler = handler; return mBuffer->flushToHandler(handler); } diff --git a/mozilla/extensions/transformiix/source/xslt/txUnknownHandler.h b/mozilla/extensions/transformiix/source/xslt/txUnknownHandler.h index 939f475105f..c18bb39b4b4 100644 --- a/mozilla/extensions/transformiix/source/xslt/txUnknownHandler.h +++ b/mozilla/extensions/transformiix/source/xslt/txUnknownHandler.h @@ -42,12 +42,12 @@ #include "txBufferingHandler.h" #include "txOutputFormat.h" -class ProcessorState; +class txExecutionState; class txUnknownHandler : public txBufferingHandler { public: - txUnknownHandler(ProcessorState* aPs); + txUnknownHandler(txExecutionState* aEs); virtual ~txUnknownHandler(); void attribute(const nsAString& aName, const PRInt32 aNsID, @@ -61,11 +61,11 @@ private: const PRInt32 aNsID); /* - * XXX we shouldn't hold to the ProcessorState, as we're supposed + * XXX we shouldn't hold to the txExecutionState, 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; + txExecutionState* mEs; }; #endif /* txUnknownHandler_h___ */ diff --git a/mozilla/extensions/transformiix/source/xslt/txVariableMap.h b/mozilla/extensions/transformiix/source/xslt/txVariableMap.h index 82d10a41333..f77c098fd8b 100644 --- a/mozilla/extensions/transformiix/source/xslt/txVariableMap.h +++ b/mozilla/extensions/transformiix/source/xslt/txVariableMap.h @@ -46,17 +46,16 @@ class txVariableMap { public: - txVariableMap(txVariableMap* aParentMap); + txVariableMap(); nsresult bindVariable(const txExpandedName& aName, ExprResult* aValue, MBool aOwned); ExprResult* getVariable(const txExpandedName& aName); + + void removeVariable(const txExpandedName& aName); private: - // Parent map of variables - txVariableMap* mParentMap; - // Map with owned variables txExpandedNameMap mOwnedVariables; @@ -65,9 +64,8 @@ private: }; -inline txVariableMap::txVariableMap(txVariableMap* aParentMap) - : mParentMap(aParentMap), - mOwnedVariables(MB_TRUE), +inline txVariableMap::txVariableMap() + : mOwnedVariables(MB_TRUE), mNonOwnedVariables(MB_FALSE) { } @@ -75,21 +73,14 @@ inline txVariableMap::txVariableMap(txVariableMap* aParentMap) inline nsresult txVariableMap::bindVariable(const txExpandedName& aName, ExprResult* aValue, MBool aOwned) { - TxObject* var = 0; - txVariableMap* map = this; - while (!var && map) { - var = map->mOwnedVariables.get(aName); - if (!var) { - var = map->mNonOwnedVariables.get(aName); - } - map = map->mParentMap; - } nsresult rv = NS_ERROR_FAILURE; - if (!var) { - if (aOwned) { + if (aOwned) { + if (!mNonOwnedVariables.get(aName)) { rv = mOwnedVariables.add(aName, aValue); } - else { + } + else { + if (!mOwnedVariables.get(aName)) { rv = mNonOwnedVariables.add(aName, aValue); } } @@ -98,17 +89,17 @@ inline nsresult txVariableMap::bindVariable(const txExpandedName& aName, inline ExprResult* txVariableMap::getVariable(const txExpandedName& aName) { - ExprResult* var = 0; - txVariableMap* map = this; - while (!var && map) { - var = (ExprResult*)map->mOwnedVariables.get(aName); - if (!var) { - var = (ExprResult*)map->mNonOwnedVariables.get(aName); - } - map = map->mParentMap; + ExprResult* var = (ExprResult*)mOwnedVariables.get(aName); + if (!var) { + var = (ExprResult*)mNonOwnedVariables.get(aName); } return var; } +inline void txVariableMap::removeVariable(const txExpandedName& aName) +{ + mOwnedVariables.remove(aName); + mNonOwnedVariables.remove(aName); +} #endif //TRANSFRMX_VARIABLEMAP_H diff --git a/mozilla/extensions/transformiix/source/xslt/txXMLOutput.cpp b/mozilla/extensions/transformiix/source/xslt/txXMLOutput.cpp index 6f55dc2f65f..c3dd574fa5e 100644 --- a/mozilla/extensions/transformiix/source/xslt/txXMLOutput.cpp +++ b/mozilla/extensions/transformiix/source/xslt/txXMLOutput.cpp @@ -40,7 +40,7 @@ const int txXMLOutput::DEFAULT_INDENT = 2; -txAttribute::txAttribute(PRInt32 aNsID, nsIAtom* aLocalName, +txOutAttr::txOutAttr(PRInt32 aNsID, nsIAtom* aLocalName, const nsAString& aValue) : mName(aNsID, aLocalName), mValue(aValue), @@ -78,15 +78,15 @@ void txXMLOutput::attribute(const nsAString& aName, XMLUtils::getLocalPart(aName, getter_AddRefs(localName)); txExpandedName att(aNsID, localName); - txAttribute* setAtt = 0; - while ((setAtt = (txAttribute*)iter.next())) { + txOutAttr* setAtt = 0; + while ((setAtt = (txOutAttr*)iter.next())) { if (setAtt->mName == att) { setAtt->mValue = aValue; break; } } if (!setAtt) { - setAtt = new txAttribute(aNsID, localName, aValue); + setAtt = new txOutAttr(aNsID, localName, aValue); mAttributes.add(setAtt); } } @@ -261,8 +261,8 @@ void txXMLOutput::closeStartTag(MBool aUseEmptyElementShorthand) mAfterEndTag = aUseEmptyElementShorthand; if (mStartTagOpen) { txListIterator iter(&mAttributes); - txAttribute* att; - while ((att = (txAttribute*)iter.next())) { + txOutAttr* att; + while ((att = (txOutAttr*)iter.next())) { *mOut << SPACE; const PRUnichar* attrVal; att->mName.mLocalName->GetUnicode(&attrVal); @@ -273,7 +273,7 @@ void txXMLOutput::closeStartTag(MBool aUseEmptyElementShorthand) printWithXMLEntities(att->mValue, MB_TRUE); *mOut << DOUBLE_QUOTE; } - delete (txAttribute*)iter.remove(); + delete (txOutAttr*)iter.remove(); } if (aUseEmptyElementShorthand) diff --git a/mozilla/extensions/transformiix/source/xslt/txXMLOutput.h b/mozilla/extensions/transformiix/source/xslt/txXMLOutput.h index 370cc2dc59b..6b78e3eec1d 100644 --- a/mozilla/extensions/transformiix/source/xslt/txXMLOutput.h +++ b/mozilla/extensions/transformiix/source/xslt/txXMLOutput.h @@ -82,9 +82,9 @@ #define XML_DECL "xml version=" #define XML_VERSION "1.0" -class txAttribute { +class txOutAttr { public: - txAttribute(PRInt32 aNsID, nsIAtom* aLocalName, const nsAString& aValue); + txOutAttr(PRInt32 aNsID, nsIAtom* aLocalName, const nsAString& aValue); txExpandedName mName; nsString mValue; MBool mShorthand; diff --git a/mozilla/extensions/transformiix/source/xslt/txXSLTAtomList.h b/mozilla/extensions/transformiix/source/xslt/txXSLTAtomList.h index 24e1d47a377..94e636bc2ca 100644 --- a/mozilla/extensions/transformiix/source/xslt/txXSLTAtomList.h +++ b/mozilla/extensions/transformiix/source/xslt/txXSLTAtomList.h @@ -85,6 +85,7 @@ TX_ATOM(doctypePublic, "doctype-public"); TX_ATOM(doctypeSystem, "doctype-system"); TX_ATOM(elements, "elements"); TX_ATOM(encoding, "encoding"); +TX_ATOM(extensionElementPrefixes, "extension-element-prefixes"); TX_ATOM(format, "format"); TX_ATOM(from, "from"); TX_ATOM(groupingSeparator, "grouping-separator"); @@ -111,6 +112,7 @@ TX_ATOM(priority, "priority"); TX_ATOM(select, "select"); TX_ATOM(standalone, "standalone"); TX_ATOM(test, "test"); +TX_ATOM(terminate, "terminate"); TX_ATOM(use, "use"); TX_ATOM(useAttributeSets, "use-attribute-sets"); TX_ATOM(value, "value"); @@ -135,8 +137,12 @@ TX_ATOM(vendorUrl, "vendor-url"); TX_ATOM(any, "any"); TX_ATOM(ascending, "ascending"); TX_ATOM(descending, "descending"); +TX_ATOM(html, "html"); TX_ATOM(lowerFirst, "lower-first"); TX_ATOM(multiple, "multiple"); +TX_ATOM(no, "no"); TX_ATOM(single, "single"); TX_ATOM(upperFirst, "upper-first"); +TX_ATOM(xml, "xml"); TX_ATOM(yes, "yes"); +TX_ATOM(_poundDefault, "#default"); diff --git a/mozilla/extensions/transformiix/source/xslt/txXSLTNumber.cpp b/mozilla/extensions/transformiix/source/xslt/txXSLTNumber.cpp index 5437936c54a..fc754dd5f40 100644 --- a/mozilla/extensions/transformiix/source/xslt/txXSLTNumber.cpp +++ b/mozilla/extensions/transformiix/source/xslt/txXSLTNumber.cpp @@ -40,9 +40,15 @@ #include "txAtoms.h" #include "primitives.h" #include +#include "Expr.h" +#include "ExprResult.h" +#include "txXSLTPatterns.h" +#include "txIXPathContext.h" -nsresult txXSLTNumber::createNumber(Element* aNumberElement, - ProcessorState* aPs, +nsresult txXSLTNumber::createNumber(Expr* aValueExpr, txPattern* aCountPattern, + txPattern* aFromPattern, LevelType aLevel, + Expr* aGroupSize, Expr* aGroupSeparator, + Expr* aFormat, txIEvalContext* aContext, nsAString& aResult) { aResult.Truncate(); @@ -51,13 +57,15 @@ nsresult txXSLTNumber::createNumber(Element* aNumberElement, // Parse format txList counters; nsAutoString head, tail; - rv = getCounters(aNumberElement, aPs, counters, head, tail); + rv = getCounters(aGroupSize, aGroupSeparator, aFormat, aContext, counters, + head, tail); NS_ENSURE_SUCCESS(rv, rv); // Create list of values to format txList values; nsAutoString valueString; - rv = getValueList(aNumberElement, aPs, values, valueString); + rv = getValueList(aValueExpr, aCountPattern, aFromPattern, aLevel, + aContext, values, valueString); NS_ENSURE_SUCCESS(rv, rv); if (!valueString.IsEmpty()) { @@ -99,23 +107,18 @@ nsresult txXSLTNumber::createNumber(Element* aNumberElement, return NS_OK; } -nsresult txXSLTNumber::getValueList(Element* aNumberElement, - ProcessorState* aPs, txList& aValues, - nsAString& aValueString) +nsresult +txXSLTNumber::getValueList(Expr* aValueExpr, txPattern* aCountPattern, + txPattern* aFromPattern, LevelType aLevel, + txIEvalContext* aContext, txList& aValues, + nsAString& aValueString) { aValueString.Truncate(); // If the value attribute exists then use that - if (aNumberElement->hasAttr(txXSLTAtoms::value, kNameSpaceID_None)) { - Expr* expr = aPs->getExpr(aNumberElement, ProcessorState::ValueAttr); - NS_ENSURE_TRUE(expr, NS_ERROR_FAILURE); - - ExprResult* result = expr->evaluate(aPs->getEvalContext()); - if (!result) { - // XXX error reporting, evaluate failed - delete expr; - return NS_ERROR_FAILURE; - } + if (aValueExpr) { + ExprResult* result = aValueExpr->evaluate(aContext); + NS_ENSURE_TRUE(result, NS_ERROR_FAILURE); double value = result->numberValue(); delete result; @@ -133,18 +136,13 @@ nsresult txXSLTNumber::getValueList(Element* aNumberElement, // Otherwise use count/from/level - txPattern *countPattern = 0, *fromPattern = 0; + txPattern* countPattern = aCountPattern; MBool ownsCountPattern = MB_FALSE; - Node* currNode = aPs->getEvalContext()->getContextNode(); + Node* currNode = aContext->getContextNode(); // Parse count- and from-attributes - if (aNumberElement->hasAttr(txXSLTAtoms::count, kNameSpaceID_None)) { - countPattern = aPs->getPattern(aNumberElement, - ProcessorState::CountAttr); - NS_ENSURE_TRUE(countPattern, NS_ERROR_FAILURE); - } - else { + if (!aCountPattern) { ownsCountPattern = MB_TRUE; txNodeTest* nodeTest = 0; switch (currNode->getNodeType()) { @@ -201,39 +199,21 @@ nsresult txXSLTNumber::getValueList(Element* aNumberElement, } } - if (aNumberElement->hasAttr(txXSLTAtoms::from, kNameSpaceID_None)) { - fromPattern = aPs->getPattern(aNumberElement, - ProcessorState::FromAttr); - if (!fromPattern) { - // XXX error reporting, parse failed - if (ownsCountPattern) { - delete countPattern; - } - return NS_ERROR_FAILURE; - } - } - // Generate list of values depending on the value of the level-attribute - nsAutoString levelStr; - nsCOMPtr level; - if (aNumberElement->getAttr(txXSLTAtoms::level, kNameSpaceID_None, levelStr)) { - level = do_GetAtom(levelStr); - } - // level = "single" - if (!level || level == txXSLTAtoms::single) { + if (aLevel == eLevelSingle) { Node* node = currNode; while (node) { - if (fromPattern && node != currNode && - fromPattern->matches(node, aPs)) { + if (aFromPattern && node != currNode && + aFromPattern->matches(node, aContext)) { break; } - if (countPattern->matches(node, aPs)) { + if (countPattern->matches(node, aContext)) { aValues.add(NS_INT32_TO_PTR(getSiblingCount(node, countPattern, - aPs))); + aContext))); break; } @@ -243,10 +223,10 @@ nsresult txXSLTNumber::getValueList(Element* aNumberElement, // Spec says to only match ancestors that are decendants of the // ancestor that matches the from-pattern, so keep going to make // sure that there is an ancestor that does. - if (fromPattern && aValues.getLength()) { + if (aFromPattern && aValues.getLength()) { node = node->getXPathParent(); while (node) { - if (fromPattern->matches(node, aPs)) { + if (aFromPattern->matches(node, aContext)) { break; } @@ -259,21 +239,21 @@ nsresult txXSLTNumber::getValueList(Element* aNumberElement, } } // level = "multiple" - else if (level == txXSLTAtoms::multiple) { + else if (aLevel == eLevelMultiple) { // find all ancestor-or-selfs that matches count until... Node* node = currNode; MBool matchedFrom = MB_FALSE; while (node) { - if (fromPattern && node != currNode && - fromPattern->matches(node, aPs)) { + if (aFromPattern && node != currNode && + aFromPattern->matches(node, aContext)) { //... we find one that matches from matchedFrom = MB_TRUE; break; } - if (countPattern->matches(node, aPs)) { + if (countPattern->matches(node, aContext)) { aValues.add(NS_INT32_TO_PTR(getSiblingCount(node, countPattern, - aPs))); + aContext))); } node = node->getXPathParent(); @@ -282,23 +262,23 @@ nsresult txXSLTNumber::getValueList(Element* aNumberElement, // Spec says to only match ancestors that are decendants of the // ancestor that matches the from-pattern, so if none did then // we shouldn't search anything - if (fromPattern && !matchedFrom) { + if (aFromPattern && !matchedFrom) { aValues.clear(); } } // level = "any" - else if (level == txXSLTAtoms::any) { + else if (aLevel == eLevelAny) { Node* node = currNode; PRInt32 value = 0; MBool matchedFrom = MB_FALSE; while (node) { - if (fromPattern && node != currNode && - fromPattern->matches(node, aPs)) { + if (aFromPattern && node != currNode && + aFromPattern->matches(node, aContext)) { matchedFrom = MB_TRUE; break; } - if (countPattern->matches(node, aPs)) { + if (countPattern->matches(node, aContext)) { ++value; } @@ -308,7 +288,7 @@ nsresult txXSLTNumber::getValueList(Element* aNumberElement, // Spec says to only count nodes that follows the first node that // matches the from pattern. So so if none did then we shouldn't // count any - if (fromPattern && !matchedFrom) { + if (aFromPattern && !matchedFrom) { value = 0; } @@ -316,10 +296,6 @@ nsresult txXSLTNumber::getValueList(Element* aNumberElement, aValues.add(NS_INT32_TO_PTR(value)); } } - else { - aPs->receiveError(NS_LITERAL_STRING("unknown value for format attribute"), - NS_ERROR_FAILURE); - } if (ownsCountPattern) { delete countPattern; @@ -330,35 +306,46 @@ nsresult txXSLTNumber::getValueList(Element* aNumberElement, nsresult -txXSLTNumber::getCounters(Element* aNumberElement, ProcessorState* aPs, - txList& aCounters, nsAString& aHead, nsAString& aTail) +txXSLTNumber::getCounters(Expr* aGroupSize, Expr* aGroupSeparator, + Expr* aFormat, txIEvalContext* aContext, + txList& aCounters, nsAString& aHead, + nsAString& aTail) { aHead.Truncate(); aTail.Truncate(); nsresult rv = NS_OK; - nsAutoString groupSizeStrAVT, groupSeparatorAVT, groupSizeStr, groupSeparator; + nsAutoString groupSeparator; PRInt32 groupSize = 0; - if (aNumberElement->getAttr(txXSLTAtoms::groupingSeparator, - kNameSpaceID_None, groupSeparatorAVT) && - aNumberElement->getAttr(txXSLTAtoms::groupingSize, - kNameSpaceID_None, groupSizeStrAVT)) { - aPs->processAttrValueTemplate(groupSeparatorAVT, aNumberElement, - groupSeparator); - aPs->processAttrValueTemplate(groupSizeStrAVT, aNumberElement, - groupSizeStr); - double size = Double::toDouble(groupSizeStr); + if (aGroupSize && aGroupSeparator) { + ExprResult* sizeRes = aGroupSize->evaluate(aContext); + NS_ENSURE_TRUE(sizeRes, NS_ERROR_FAILURE); + + nsAutoString sizeStr; + sizeRes->stringValue(sizeStr); + delete sizeRes; + + double size = Double::toDouble(sizeStr); groupSize = (PRInt32)size; if ((double)groupSize != size) { groupSize = 0; } + + ExprResult* sepRes = aGroupSeparator->evaluate(aContext); + NS_ENSURE_TRUE(sepRes, NS_ERROR_FAILURE); + + sepRes->stringValue(groupSeparator); + delete sepRes; } - nsAutoString formatAVT, format; - if (aNumberElement->getAttr(txXSLTAtoms::format, kNameSpaceID_None, - formatAVT)) { - aPs->processAttrValueTemplate(formatAVT, aNumberElement, format); + nsAutoString format; + if (aFormat) { + ExprResult* formatRes = aFormat->evaluate(aContext); + NS_ENSURE_TRUE(formatRes, NS_ERROR_FAILURE); + + formatRes->stringValue(format); + delete formatRes; } PRUint32 formatLen = format.Length(); PRUint32 formatPos = 0; diff --git a/mozilla/extensions/transformiix/source/xslt/txXSLTNumber.h b/mozilla/extensions/transformiix/source/xslt/txXSLTNumber.h index 7d4f9660267..c6e9ae6aa53 100644 --- a/mozilla/extensions/transformiix/source/xslt/txXSLTNumber.h +++ b/mozilla/extensions/transformiix/source/xslt/txXSLTNumber.h @@ -39,21 +39,40 @@ #ifndef TRANSFRMX_TXXSLTNUMBER_H #define TRANSFRMX_TXXSLTNUMBER_H -#include "ProcessorState.h" #include "txError.h" +#include "List.h" +#include "nsString.h" + +class Expr; +class Node; +class txPattern; +class txIEvalContext; +class txIMatchContext; class txXSLTNumber { - public: - static nsresult createNumber(Element* aNumberElement, ProcessorState* aPs, - nsAString& aResult); -private: - static nsresult getValueList(Element* aNumberElement, ProcessorState* aPs, - txList& aValues, nsAString& aValueString); + enum LevelType { + eLevelSingle, + eLevelMultiple, + eLevelAny + }; - static nsresult getCounters(Element* aNumberElement, ProcessorState* aPs, - txList& aCounters, - nsAString& aHead, nsAString& aTail); + static nsresult createNumber(Expr* aValueExpr, txPattern* aCountPattern, + txPattern* aFromPattern, LevelType aLevel, + Expr* aGroupSize, Expr* aGroupSeparator, + Expr* aFormat, txIEvalContext* aContext, + nsAString& aResult); + +private: + static nsresult getValueList(Expr* aValueExpr, txPattern* aCountPattern, + txPattern* aFromPattern, LevelType aLevel, + txIEvalContext* aContext, txList& aValues, + nsAString& aValueString); + + static nsresult getCounters(Expr* aGroupSize, Expr* aGroupSeparator, + Expr* aFormat, txIEvalContext* aContext, + txList& aCounters, nsAString& aHead, + nsAString& aTail); static PRInt32 getSiblingCount(Node* aNode, txPattern* aCountPattern, txIMatchContext* aContext); diff --git a/mozilla/extensions/transformiix/source/xslt/txXSLTPatterns.cpp b/mozilla/extensions/transformiix/source/xslt/txXSLTPatterns.cpp index cb61860efda..38c8ad51682 100644 --- a/mozilla/extensions/transformiix/source/xslt/txXSLTPatterns.cpp +++ b/mozilla/extensions/transformiix/source/xslt/txXSLTPatterns.cpp @@ -37,7 +37,7 @@ * ***** END LICENSE BLOCK ***** */ #include "nsReadableUtils.h" -#include "ProcessorState.h" +#include "txExecutionState.h" #include "txXSLTPatterns.h" #include "txNodeSetContext.h" #include "txForwardContext.h" @@ -412,15 +412,15 @@ txKeyPattern::~txKeyPattern() MBool txKeyPattern::matches(Node* aNode, txIMatchContext* aContext) { + txExecutionState* es = (txExecutionState*)aContext->getPrivateContext(); Document* contextDoc; if (aNode->getNodeType() == Node::DOCUMENT_NODE) contextDoc = (Document*)aNode; else contextDoc = aNode->getOwnerDocument(); const NodeSet* nodes = 0; - nsresult rv = mProcessorState->getKeyNodes(mName, contextDoc, mValue, - PR_TRUE, &nodes); - if (NS_FAILED(rv) || !nodes || nodes->isEmpty()) + nsresult rv = es->getKeyNodes(mName, contextDoc, mValue, PR_TRUE, &nodes); + if (NS_FAILED(rv) || !nodes) return MB_FALSE; MBool isTrue = nodes->contains(aNode); return isTrue; diff --git a/mozilla/extensions/transformiix/source/xslt/txXSLTPatterns.h b/mozilla/extensions/transformiix/source/xslt/txXSLTPatterns.h index 69fd2c8363f..3b06d7b37dc 100644 --- a/mozilla/extensions/transformiix/source/xslt/txXSLTPatterns.h +++ b/mozilla/extensions/transformiix/source/xslt/txXSLTPatterns.h @@ -174,10 +174,9 @@ private: class txKeyPattern : public txPattern { public: - txKeyPattern(ProcessorState* aPs, nsIAtom* aPrefix, nsIAtom* aLocalName, + txKeyPattern(nsIAtom* aPrefix, nsIAtom* aLocalName, PRInt32 aNSID, const nsAString& aValue) - : mProcessorState(aPs), mName(aNSID, aLocalName), mPrefix(aPrefix), - mValue(aValue) + : mName(aNSID, aLocalName), mPrefix(aPrefix), mValue(aValue) { } @@ -186,7 +185,6 @@ public: TX_DECL_PATTERN; private: - ProcessorState* mProcessorState; txExpandedName mName; nsIAtom* mPrefix; nsString mValue; diff --git a/mozilla/extensions/transformiix/source/xslt/txXSLTProcessor.cpp b/mozilla/extensions/transformiix/source/xslt/txXSLTProcessor.cpp new file mode 100644 index 00000000000..340f51ae1f1 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/txXSLTProcessor.cpp @@ -0,0 +1,113 @@ +/* -*- 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 + * Jonas Sicking. + * Portions created by the Initial Developer are Copyright (C) 2002 + * Jonas Sicking. All Rights Reserved. + * + * Contributor(s): + * Jonas Sicking + * + * 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 "txXSLTProcessor.h" +#include "txInstructions.h" +#include "txAtoms.h" +#include "TxLog.h" +#include "txStylesheetCompileHandlers.h" +#include "txExecutionState.h" +#ifdef TX_EXE +#include "txHTMLOutput.h" +#endif + +TX_LG_IMPL; + +/* static */ +MBool +txXSLTProcessor::init() +{ + TX_LG_CREATE; + +#ifdef TX_EXE + if (!txNamespaceManager::init()) + return MB_FALSE; + + if (NS_FAILED(txHTMLOutput::init())) { + return MB_FALSE; + } +#endif + + if (!txHTMLAtoms::init()) + return MB_FALSE; + if (!txXMLAtoms::init()) + return MB_FALSE; + if (!txXPathAtoms::init()) + return MB_FALSE; + if (!txXSLTAtoms::init()) + return MB_FALSE; + + if (!txHandlerTable::init()) + return MB_FALSE; + + return MB_TRUE; +} + +/* static */ +void +txXSLTProcessor::shutdown() +{ +#ifdef TX_EXE + txNamespaceManager::shutdown(); + txHTMLOutput::shutdown(); +#endif + + txHTMLAtoms::shutdown(); + txXMLAtoms::shutdown(); + txXPathAtoms::shutdown(); + txXSLTAtoms::shutdown(); + + txHandlerTable::shutdown(); + + TX_LG_DELETE; +} + + +/* static */ +nsresult +txXSLTProcessor::execute(txExecutionState& aEs) +{ + nsresult rv = NS_OK; + txInstruction* instr; + while ((instr = aEs.getNextInstruction())) { + rv = instr->execute(aEs); + NS_ENSURE_SUCCESS(rv, rv); + } + + return NS_OK; +} diff --git a/mozilla/extensions/transformiix/source/xslt/txXSLTProcessor.h b/mozilla/extensions/transformiix/source/xslt/txXSLTProcessor.h new file mode 100644 index 00000000000..5711422d6ce --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/txXSLTProcessor.h @@ -0,0 +1,61 @@ +/* -*- 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 + * Jonas Sicking. + * Portions created by the Initial Developer are Copyright (C) 2002 + * Jonas Sicking. All Rights Reserved. + * + * Contributor(s): + * Jonas Sicking + * + * 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_TXXSLTPROCESSOR_H +#define TRANSFRMX_TXXSLTPROCESSOR_H + +#include "txExecutionState.h" + +class txXSLTProcessor +{ +public: + /** + * Initialisation and shutdown routines. Initilizes and cleansup all + * dependant classes + */ + static MBool init(); + static void shutdown(); + + + static nsresult execute(txExecutionState& aEs); + + // once we want to have interuption we should probably have functions for + // running X number of steps or running until a condition is true. +}; + +#endif diff --git a/mozilla/extensions/transformiix/source/xslt/util/txNodeSorter.cpp b/mozilla/extensions/transformiix/source/xslt/util/txNodeSorter.cpp index a1975af9a37..91749a24738 100644 --- a/mozilla/extensions/transformiix/source/xslt/util/txNodeSorter.cpp +++ b/mozilla/extensions/transformiix/source/xslt/util/txNodeSorter.cpp @@ -38,11 +38,14 @@ * ***** END LICENSE BLOCK ***** */ #include "txNodeSorter.h" -#include "ProcessorState.h" +#include "txExecutionState.h" #include "txXPathResultComparator.h" #include "txAtoms.h" #include "txForwardContext.h" +#include "ExprResult.h" +#include "Expr.h" #include "txStringUtils.h" +#include "NodeSet.h" /* * Sorts Nodes as specified by the W3C XSLT 1.0 Recommendation @@ -50,9 +53,7 @@ #define DEFAULT_LANG NS_LITERAL_STRING("en") -txNodeSorter::txNodeSorter(ProcessorState* aPs) : mPs(aPs), - mNKeys(0), - mDefaultExpr(0) +txNodeSorter::txNodeSorter() : mNKeys(0) { } @@ -64,107 +65,116 @@ txNodeSorter::~txNodeSorter() delete key->mComparator; delete key; } - delete mDefaultExpr; } -MBool txNodeSorter::addSortElement(Element* aSortElement) +nsresult +txNodeSorter::addSortElement(Expr* aSelectExpr, Expr* aLangExpr, + Expr* aDataTypeExpr, Expr* aOrderExpr, + Expr* aCaseOrderExpr, txIEvalContext* aContext) { SortKey* key = new SortKey; - if (!key) { - // XXX ErrorReport: out of memory - return MB_FALSE; - } - - // Get common attributes - nsAutoString attrValue; + NS_ENSURE_TRUE(key, NS_ERROR_OUT_OF_MEMORY); // Select - if (aSortElement->hasAttr(txXSLTAtoms::select, kNameSpaceID_None)) - key->mExpr = mPs->getExpr(aSortElement, ProcessorState::SelectAttr); - else { - if (!mDefaultExpr) { - txNodeTest* test = new txNodeTypeTest(txNodeTypeTest::NODE_TYPE); - mDefaultExpr = new LocationStep(test, LocationStep::SELF_AXIS); - } - key->mExpr = mDefaultExpr; - } - - if (!key->mExpr) { - // XXX ErrorReport: Out of memory - delete key; - return MB_FALSE; - } + key->mExpr = aSelectExpr; // Order - MBool ascending; - MBool hasAttr = getAttrAsAVT(aSortElement, txXSLTAtoms::order, attrValue); - if (!hasAttr || TX_StringEqualsAtom(attrValue, txXSLTAtoms::ascending)) { - ascending = MB_TRUE; - } - else if (TX_StringEqualsAtom(attrValue, txXSLTAtoms::descending)) { - ascending = MB_FALSE; - } - else { - delete key; - // XXX ErrorReport: unknown value for order attribute - return MB_FALSE; + MBool ascending = MB_TRUE; + if (aOrderExpr) { + ExprResult* exprRes = aOrderExpr->evaluate(aContext); + NS_ENSURE_TRUE(exprRes, NS_ERROR_FAILURE); + + nsAutoString attrValue; + exprRes->stringValue(attrValue); + delete exprRes; + + if (TX_StringEqualsAtom(attrValue, txXSLTAtoms::descending)) { + ascending = MB_FALSE; + } + else if (!TX_StringEqualsAtom(attrValue, txXSLTAtoms::ascending)) { + delete key; + // XXX ErrorReport: unknown value for order attribute + return NS_ERROR_XSLT_BAD_VALUE; + } } // Create comparator depending on datatype nsAutoString dataType; - hasAttr = getAttrAsAVT(aSortElement, txXSLTAtoms::dataType, dataType); - if (!hasAttr || TX_StringEqualsAtom(dataType, txXSLTAtoms::text)) { + if (aDataTypeExpr) { + ExprResult* exprRes = aDataTypeExpr->evaluate(aContext); + NS_ENSURE_TRUE(exprRes, NS_ERROR_FAILURE); + + exprRes->stringValue(dataType); + delete exprRes; + } + + if (!aDataTypeExpr || TX_StringEqualsAtom(dataType, txXSLTAtoms::text)) { // Text comparator // Language nsAutoString lang; - if (!getAttrAsAVT(aSortElement, txXSLTAtoms::lang, lang)) - lang.Append(DEFAULT_LANG); + if (aLangExpr) { + ExprResult* exprRes = aLangExpr->evaluate(aContext); + NS_ENSURE_TRUE(exprRes, NS_ERROR_FAILURE); - // Case-order - MBool upperFirst; - hasAttr = getAttrAsAVT(aSortElement, txXSLTAtoms::caseOrder, attrValue); - if (!hasAttr || TX_StringEqualsAtom(attrValue, - txXSLTAtoms::upperFirst)) { - upperFirst = MB_TRUE; - } - else if (TX_StringEqualsAtom(attrValue, txXSLTAtoms::lowerFirst)) { - upperFirst = MB_FALSE; + exprRes->stringValue(lang); + delete exprRes; } else { - // XXX ErrorReport: unknown value for case-order attribute - delete key; - return MB_FALSE; + lang.Append(DEFAULT_LANG); + } + + // Case-order + + + MBool upperFirst = MB_TRUE; + if (aCaseOrderExpr) { + ExprResult* exprRes = aCaseOrderExpr->evaluate(aContext); + NS_ENSURE_TRUE(exprRes, NS_ERROR_FAILURE); + + nsAutoString attrValue; + exprRes->stringValue(attrValue); + delete exprRes; + + if (TX_StringEqualsAtom(attrValue, txXSLTAtoms::lowerFirst)) { + upperFirst = MB_FALSE; + } + else if (!TX_StringEqualsAtom(attrValue, + txXSLTAtoms::upperFirst)) { + delete key; + // XXX ErrorReport: unknown value for case-order attribute + return NS_ERROR_XSLT_BAD_VALUE; + } } key->mComparator = new txResultStringComparator(ascending, upperFirst, lang); + NS_ENSURE_TRUE(key->mComparator, NS_ERROR_OUT_OF_MEMORY); } else if (TX_StringEqualsAtom(dataType, txXSLTAtoms::number)) { // Number comparator key->mComparator = new txResultNumberComparator(ascending); + NS_ENSURE_TRUE(key->mComparator, NS_ERROR_OUT_OF_MEMORY); } else { // XXX ErrorReport: unknown data-type - return MB_FALSE; - } + delete key; - if (!key->mComparator) { - // XXX ErrorReport: out of memory - return MB_FALSE; + return NS_ERROR_XSLT_BAD_VALUE; } mSortKeys.add(key); mNKeys++; - return MB_TRUE; + + return NS_OK; } -MBool txNodeSorter::sortNodeSet(NodeSet* aNodes) +nsresult txNodeSorter::sortNodeSet(NodeSet* aNodes, txExecutionState* aEs) { if (mNKeys == 0) - return MB_TRUE; + return NS_OK; txList sortedNodes; txListIterator iter(&sortedNodes); @@ -183,11 +193,11 @@ MBool txNodeSorter::sortNodeSet(NodeSet* aNodes) sNode->clear(mNKeys); delete sNode; } - return MB_FALSE; + return NS_ERROR_OUT_OF_MEMORY; } iter.reset(); SortableNode* compNode = (SortableNode*)iter.next(); - while (compNode && (compareNodes(currNode, compNode, aNodes) > 0)) { + while (compNode && (compareNodes(currNode, compNode, aNodes, aEs) > 0)) { compNode = (SortableNode*)iter.next(); } // ... and insert in sorted list @@ -206,12 +216,13 @@ MBool txNodeSorter::sortNodeSet(NodeSet* aNodes) delete sNode; } - return MB_TRUE; + return NS_OK; } int txNodeSorter::compareNodes(SortableNode* aSNode1, SortableNode* aSNode2, - NodeSet* aNodes) + NodeSet* aNodes, + txExecutionState* aEs) { txListIterator iter(&mSortKeys); int i; @@ -221,10 +232,10 @@ int txNodeSorter::compareNodes(SortableNode* aSNode1, SortKey* key = (SortKey*)iter.next(); // Lazy create sort values if (!aSNode1->mSortValues[i]) { - txForwardContext evalContext(mPs, aSNode1->mNode, aNodes); - txIEvalContext* priorEC = mPs->setEvalContext(&evalContext); + txForwardContext evalContext(aEs->getEvalContext(), aSNode1->mNode, aNodes); + aEs->pushEvalContext(&evalContext); ExprResult* res = key->mExpr->evaluate(&evalContext); - mPs->setEvalContext(priorEC); + aEs->popEvalContext(); if (!res) { // XXX ErrorReport return -1; @@ -237,10 +248,10 @@ int txNodeSorter::compareNodes(SortableNode* aSNode1, delete res; } if (!aSNode2->mSortValues[i]) { - txForwardContext evalContext(mPs, aSNode2->mNode, aNodes); - txIEvalContext* priorEC = mPs->setEvalContext(&evalContext); + txForwardContext evalContext(aEs->getEvalContext(), aSNode2->mNode, aNodes); + aEs->pushEvalContext(&evalContext); ExprResult* res = key->mExpr->evaluate(&evalContext); - mPs->setEvalContext(priorEC); + aEs->popEvalContext(); if (!res) { // XXX ErrorReport return -1; @@ -263,20 +274,6 @@ int txNodeSorter::compareNodes(SortableNode* aSNode1, return 0; } -MBool txNodeSorter::getAttrAsAVT(Element* aSortElement, - nsIAtom* aAttrName, - nsAString& aResult) -{ - aResult.Truncate(); - - nsAutoString attValue; - if (!aSortElement->getAttr(aAttrName, kNameSpaceID_None, attValue)) - return MB_FALSE; - - mPs->processAttrValueTemplate(attValue, aSortElement, aResult); - return MB_TRUE; -} - txNodeSorter::SortableNode::SortableNode(Node* aNode, int aNValues) { mNode = aNode; diff --git a/mozilla/extensions/transformiix/source/xslt/util/txNodeSorter.h b/mozilla/extensions/transformiix/source/xslt/util/txNodeSorter.h index 2596e10dd0f..dcbd0d1dedb 100644 --- a/mozilla/extensions/transformiix/source/xslt/util/txNodeSorter.h +++ b/mozilla/extensions/transformiix/source/xslt/util/txNodeSorter.h @@ -48,9 +48,10 @@ class Element; class Expr; class Node; class NodeSet; -class ProcessorState; +class txExecutionState; class TxObject; class txXPathResultComparator; +class txIEvalContext; /* * Sorts Nodes as specified by the W3C XSLT 1.0 Recommendation @@ -59,11 +60,13 @@ class txXPathResultComparator; class txNodeSorter { public: - txNodeSorter(ProcessorState* aPs); + txNodeSorter(); ~txNodeSorter(); - MBool addSortElement(Element* aSortElement); - MBool sortNodeSet(NodeSet* aNodes); + nsresult addSortElement(Expr* aSelectExpr, Expr* aLangExpr, + Expr* aDataTypeExpr, Expr* aOrderExpr, + Expr* aCaseOrderExpr, txIEvalContext* aContext); + nsresult sortNodeSet(NodeSet* aNodes, txExecutionState* aEs); private: class SortableNode @@ -82,16 +85,15 @@ private: int compareNodes(SortableNode* sNode1, SortableNode* sNode2, - NodeSet* aNodes); + NodeSet* aNodes, + txExecutionState* aEs); MBool getAttrAsAVT(Element* aSortElement, nsIAtom* aAttrName, nsAString& aResult); txList mSortKeys; - ProcessorState* mPs; int mNKeys; - Expr* mDefaultExpr; }; #endif diff --git a/mozilla/layout/build/Makefile.in b/mozilla/layout/build/Makefile.in index 6f7e41975b0..3094a75b63a 100644 --- a/mozilla/layout/build/Makefile.in +++ b/mozilla/layout/build/Makefile.in @@ -96,7 +96,6 @@ SHARED_LIBRARY_LIBS = \ $(DIST)/lib/$(LIB_PREFIX)gkconhtmlstyle_s.$(LIB_SUFFIX) \ $(DIST)/lib/$(LIB_PREFIX)gkconxmlcon_s.$(LIB_SUFFIX) \ $(DIST)/lib/$(LIB_PREFIX)gkconxmldoc_s.$(LIB_SUFFIX) \ - $(DIST)/lib/$(LIB_PREFIX)gkconxsldoc_s.$(LIB_SUFFIX) \ $(DIST)/lib/$(LIB_PREFIX)gkconxbl_s.$(LIB_SUFFIX) \ $(DIST)/lib/$(LIB_PREFIX)gkconxuldoc_s.$(LIB_SUFFIX) \ $(DIST)/lib/$(LIB_PREFIX)gkconshared_s.$(LIB_SUFFIX) \