Compiled XSLT stylesheets. Improves speed, implements forwards-compatible-parsing and handling of unknown extension-elements. Also fixes some random edgecasebugs such as recursive merged named-attribute-sets and empty strings in copy-of.

Patch mainly by sicking, but large parts also by Pike and peterv.

Tracker is bug 185797. r=Pike/sicking rs=peterv.


git-svn-id: svn://10.0.0.236/trunk@140310 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
sicking%bigfoot.com 2003-03-26 01:10:14 +00:00
parent 325f6d6a00
commit 64ce860e2a
96 changed files with 9991 additions and 5706 deletions

View File

@ -1808,20 +1808,6 @@
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsTransformMediator.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsXSLContentSink.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsElementMap.cpp</PATH>
@ -3071,16 +3057,6 @@
<PATH>nsStyleContext.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsTransformMediator.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsXSLContentSink.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsElementMap.cpp</PATH>
@ -5168,20 +5144,6 @@
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsTransformMediator.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsXSLContentSink.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsElementMap.cpp</PATH>
@ -6431,16 +6393,6 @@
<PATH>nsStyleContext.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsTransformMediator.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsXSLContentSink.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsElementMap.cpp</PATH>
@ -7871,20 +7823,6 @@
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
</GROUP>
<GROUP><NAME>xsl</NAME>
<FILEREF>
<TARGETNAME>content.o</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsTransformMediator.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<TARGETNAME>content.o</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsXSLContentSink.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
</GROUP>
<GROUP><NAME>xul/content</NAME>
<FILEREF>
<TARGETNAME>content.o</TARGETNAME>

View File

@ -95,16 +95,6 @@
<SETTING><NAME>FrameworkPath</NAME><VALUE>false</VALUE></SETTING>
<SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>
</SETTING>
<SETTING>
<SETTING><NAME>SearchPath</NAME>
<SETTING><NAME>Path</NAME><VALUE>::xsl:document:src:</VALUE></SETTING>
<SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>
<SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>
</SETTING>
<SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>
<SETTING><NAME>FrameworkPath</NAME><VALUE>false</VALUE></SETTING>
<SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>
</SETTING>
<SETTING>
<SETTING><NAME>SearchPath</NAME>
<SETTING><NAME>Path</NAME><VALUE>::xul:document:public:</VALUE></SETTING>
@ -1154,16 +1144,6 @@
<SETTING><NAME>FrameworkPath</NAME><VALUE>false</VALUE></SETTING>
<SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>
</SETTING>
<SETTING>
<SETTING><NAME>SearchPath</NAME>
<SETTING><NAME>Path</NAME><VALUE>::xsl:document:src:</VALUE></SETTING>
<SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>
<SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>
</SETTING>
<SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>
<SETTING><NAME>FrameworkPath</NAME><VALUE>false</VALUE></SETTING>
<SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>
</SETTING>
<SETTING>
<SETTING><NAME>SearchPath</NAME>
<SETTING><NAME>Path</NAME><VALUE>::xul:document:public:</VALUE></SETTING>

View File

@ -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<nsIDOMDocument> 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<nsILoadGroup> loadGroup;
rv = mDocument->GetDocumentLoadGroup(getter_AddRefs(loadGroup));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIChannel> channel;
rv = NS_NewChannel(getter_AddRefs(channel), aUrl);
if (NS_FAILED(rv)) return rv;
channel->SetLoadGroup(loadGroup);
nsCOMPtr<nsIHttpChannel> 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<nsIDocument> styleDoc = do_CreateInstance(kXMLDocumentCID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
// Create the XSL content sink
nsCOMPtr<nsIXMLContentSink> sink;
rv = NS_NewXSLContentSink(getter_AddRefs(sink), mXSLTransformMediator, styleDoc, aUrl, mWebShell);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIStreamListener> 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<nsIScriptSecurityManager> secMan =
nsCOMPtr<nsIScriptSecurityManager> 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");

View File

@ -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<nsISupportsArray> mContentStack;
nsCOMPtr<nsINodeInfoManager> mNodeInfoManager;
nsCOMPtr<nsITransformMediator> mXSLTransformMediator;
nsCOMPtr<nsIDocumentTransformer> mXSLTProcessor;
};
#endif // nsXMLContentSink_h__

View File

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

View File

@ -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

View File

@ -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

View File

@ -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<nsIDOMDocument> 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;
}

View File

@ -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<nsIDocumentTransformer> mTransformer;
nsCOMPtr<nsIDOMNode> mSourceDOM;
nsCOMPtr<nsIDOMNode> mStyleDOM;
nsCOMPtr<nsIDOMDocument> mResultDoc;
nsCOMPtr<nsITransformObserver> mObserver;
};
#endif // nsTransformMediator_h__

View File

@ -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<nsIXMLContentSink> 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<nsIDOMNode> styleNode;
nsCOMPtr<nsIURL> 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<nsIDOMDocument> styleDoc = do_QueryInterface(mDocument);
NS_ENSURE_TRUE(styleDoc, NS_ERROR_NO_INTERFACE);
nsCOMPtr<nsIDOMElement> 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 <?xml-stylesheet?>
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<nsITransformMediator> mediator = mXSLTransformMediator;
nsCOMPtr<nsIChannel> channel;
nsCOMPtr<nsILoadGroup> loadGroup;
mParser->GetChannel(getter_AddRefs(channel));
mDocument->GetDocumentLoadGroup(getter_AddRefs(loadGroup));
mDocument->Reset(channel, loadGroup);
nsXMLContentSink::ReportError(aErrorText, aSourceText);
if (mediator) {
nsCOMPtr<nsIDOMNode> 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;
}

View File

@ -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__

View File

@ -2,5 +2,4 @@
# This is a list of local files which get copied to the mozilla:dist:content directory
#
nsITransformMediator.h
nsIDocumentTransformer.h

View File

@ -47,7 +47,6 @@ XPIDL_MODULE = content_xslt
EXPORTS = \
nsIDocumentTransformer.h \
nsITransformMediator.h \
$(NULL)
XPIDLSRCS = \

View File

@ -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__

View File

@ -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) \

View File

@ -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

View File

@ -1069,13 +1069,6 @@
<FILEKIND>Text</FILEKIND>
<FILEFLAGS></FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>ProcessorState.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS></FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>ExprLexer.cpp</PATH>
@ -1307,13 +1300,6 @@
<FILEKIND>Text</FILEKIND>
<FILEFLAGS></FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>XSLTProcessor.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS></FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>txXMLParser.cpp</PATH>
@ -1363,13 +1349,6 @@
<FILEKIND>Text</FILEKIND>
<FILEFLAGS></FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>Map.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS></FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>XSLTProcessorModule.cpp</PATH>
@ -1531,6 +1510,69 @@
<FILEKIND>Text</FILEKIND>
<FILEFLAGS></FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>txNamespaceMap.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>txExecutionState.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>txInstructions.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>txStylesheet.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>txStylesheetCompileHandlers.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>txStylesheetCompiler.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>txToplevelItems.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>txXSLTProcessor.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>txMozillaStylesheetCompiler.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
</FILELIST>
<LINKORDER>
<FILEREF>
@ -1603,11 +1645,6 @@
<PATH>NodeSet.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>ProcessorState.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>ExprLexer.cpp</PATH>
@ -1763,11 +1800,6 @@
<PATH>MozillaAttr.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>XSLTProcessor.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>MozillaDocument.cpp</PATH>
@ -1828,11 +1860,6 @@
<PATH>FunctionAvailableFnCall.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>Map.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>XSLTProcessorModule.cpp</PATH>
@ -1943,6 +1970,51 @@
<PATH>txUnknownHandler.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>txNamespaceMap.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>txExecutionState.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>txInstructions.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>txStylesheet.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>txStylesheetCompileHandlers.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>txStylesheetCompiler.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>txToplevelItems.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>txXSLTProcessor.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>txMozillaStylesheetCompiler.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
</LINKORDER>
</TARGET>
<TARGET>
@ -2905,13 +2977,6 @@
<FILEKIND>Text</FILEKIND>
<FILEFLAGS></FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>ProcessorState.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS></FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>ExprLexer.cpp</PATH>
@ -3143,13 +3208,6 @@
<FILEKIND>Text</FILEKIND>
<FILEFLAGS></FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>XSLTProcessor.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS></FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>NSPR20.shlb</PATH>
@ -3227,13 +3285,6 @@
<FILEKIND>Text</FILEKIND>
<FILEFLAGS></FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>Map.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS></FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>XSLTProcessorModule.cpp</PATH>
@ -3423,6 +3474,69 @@
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>txNamespaceMap.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>txExecutionState.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>txInstructions.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>txStylesheet.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>txStylesheetCompileHandlers.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>txStylesheetCompiler.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>txToplevelItems.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>txXSLTProcessor.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>txMozillaStylesheetCompiler.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
</FILELIST>
<LINKORDER>
<FILEREF>
@ -3455,11 +3569,6 @@
<PATH>NodeSet.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>ProcessorState.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>ExprLexer.cpp</PATH>
@ -3615,11 +3724,6 @@
<PATH>MozillaAttr.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>XSLTProcessor.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>MozillaDocument.cpp</PATH>
@ -3700,11 +3804,6 @@
<PATH>FunctionAvailableFnCall.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>Map.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>XSLTProcessorModule.cpp</PATH>
@ -3835,6 +3934,51 @@
<PATH>txUnknownHandler.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>txNamespaceMap.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>txExecutionState.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>txInstructions.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>txStylesheet.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>txStylesheetCompileHandlers.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>txStylesheetCompiler.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>txToplevelItems.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>txXSLTProcessor.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>txMozillaStylesheetCompiler.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
</LINKORDER>
</TARGET>
</TARGETLIST>
@ -3859,12 +4003,6 @@
<PATH>List.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<TARGETNAME>transformiixDebug.shlb</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>Map.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<TARGETNAME>transformiixDebug.shlb</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
@ -3883,6 +4021,12 @@
<PATH>txExpandedNameMap.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<TARGETNAME>transformiixDebug.shlb</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>txNamespaceMap.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<TARGETNAME>transformiixDebug.shlb</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
@ -4166,7 +4310,19 @@
<FILEREF>
<TARGETNAME>transformiixDebug.shlb</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>ProcessorState.cpp</PATH>
<PATH>txExecutionState.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<TARGETNAME>transformiixDebug.shlb</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>txInstructions.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<TARGETNAME>transformiixDebug.shlb</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>txMozillaStylesheetCompiler.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
@ -4205,12 +4361,36 @@
<PATH>txRtfHandler.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<TARGETNAME>transformiixDebug.shlb</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>txStylesheet.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<TARGETNAME>transformiixDebug.shlb</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>txStylesheetCompileHandlers.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<TARGETNAME>transformiixDebug.shlb</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>txStylesheetCompiler.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<TARGETNAME>transformiixDebug.shlb</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>txTextHandler.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<TARGETNAME>transformiixDebug.shlb</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>txToplevelItems.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<TARGETNAME>transformiixDebug.shlb</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
@ -4238,7 +4418,7 @@
<FILEREF>
<TARGETNAME>transformiixDebug.shlb</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>XSLTProcessor.cpp</PATH>
<PATH>txXSLTProcessor.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<GROUP><NAME>functions</NAME>

View File

@ -105,6 +105,7 @@ protected:
ListItem* remove(ListItem* sItem);
private:
txList(const txList& aOther); // not implemented
ListItem* firstItem;
ListItem* lastItem;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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) {

View File

@ -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

View File

@ -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 <jonas@sicking.cc>
*
* 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<nsIAtom> prefix = do_GetAtom(aPrefix);
return lookupNamespace(prefix);
}
PRInt32
txNamespaceMap::lookupNamespaceWithDefault(const nsAString& aPrefix)
{
nsCOMPtr<nsIAtom> prefix = do_GetAtom(aPrefix);
if (prefix != txXSLTAtoms::_poundDefault) {
return lookupNamespace(prefix);
}
return lookupNamespace(nsnull);
}

View File

@ -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 <sicking@bigfoot.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#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<nsIAtom> mPrefixes;
nsVoidArray mNamespaces;
};
#endif //TRANSFRMX_TXNAMESPACEMAP_H

View File

@ -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

View File

@ -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();

View File

@ -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;

View File

@ -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<txStylesheet> 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;
}

View File

@ -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<nsIAtom> 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

View File

@ -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);

View File

@ -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<txNodeTest> aNodeTest, LocationStepType aAxisIdentifier);
TX_DECL_EXPR;
private:
txNodeTest* mNodeTest;
nsAutoPtr<txNodeTest> mNodeTest;
LocationStepType mAxisIdentifier;
void fromDescendants(Node* node, txIMatchContext* aContext,

View File

@ -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<txNodeTest> 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;
}

View File

@ -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;
}

View File

@ -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<txNodeTest> 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 -/
//-----------------------------/

View File

@ -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)
{

View File

@ -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!!!");

View File

@ -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

View File

@ -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!!!");

View File

@ -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

View File

@ -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!!!");

View File

@ -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)

File diff suppressed because it is too large Load Diff

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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)

View File

@ -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;
}

View File

@ -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 ||

View File

@ -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 ||

View File

@ -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

View File

@ -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) {

View File

@ -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<txNamespaceMap> 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<txNamespaceMap> 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<txNamespaceMap> 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<txNamespaceMap> 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<txNamespaceMap> mMappings;
};
#endif

View File

@ -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 <math.h>
#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);

View File

@ -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<txPattern> aMatch, nsAutoPtr<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 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<txPattern> matchPattern;
nsAutoPtr<Expr> 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;
};

View File

@ -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<txPattern> aMatch, nsAutoPtr<Expr> aUse)
{
if (!aMatch || !aUse)
return PR_FALSE;
Key* key = new Key;
nsAutoPtr<Key> 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; i<attrs->getLength(); 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; i<res->size(); i++) {

View File

@ -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 <jonas@sicking.cc>
*
* 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<txRtfHandler> 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;
}

View File

@ -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 <jonas@sicking.cc>
*
* 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<txStylesheet> mStylesheet;
private:
txStack mReturnStack;
txStack mLocalVarsStack;
txStack mEvalContextStack;
txStack mIntStack;
txStack mResultHandlerStack;
txStack mParamStack;
nsStringArray mStringStack;
txInstruction* mNextInstruction;
txVariableMap* mLocalVariables;
txVariableMap mGlobalVariableValues;
nsAutoPtr<ExprResult> 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

View File

@ -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<nsIAtom> 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);
}

File diff suppressed because it is too large Load Diff

View File

@ -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 <jonas@sicking.cc>
*
* 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<Expr> aName, nsAutoPtr<Expr> aNamespace,
txNamespaceMap* aMappings);
TX_DECL_TXINSTRUCTION
nsAutoPtr<Expr> mName;
nsAutoPtr<Expr> mNamespace;
nsRefPtr<txNamespaceMap> 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<Expr> aCondition, txInstruction* aTarget);
TX_DECL_TXINSTRUCTION
nsAutoPtr<Expr> 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<Expr> aSelect);
TX_DECL_TXINSTRUCTION
nsAutoPtr<Expr> 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<Expr> aValue);
TX_DECL_TXINSTRUCTION
PRInt32 mNamespaceID;
nsCOMPtr<nsIAtom> mLocalName;
nsCOMPtr<nsIAtom> mPrefix;
nsAutoPtr<Expr> mValue;
};
class txMessage : public txInstruction
{
public:
txMessage(PRBool aTerminate);
TX_DECL_TXINSTRUCTION
PRBool mTerminate;
};
class txNumber : public txInstruction
{
public:
txNumber(txXSLTNumber::LevelType aLevel, nsAutoPtr<txPattern> aCount,
nsAutoPtr<txPattern> aFrom, nsAutoPtr<Expr> aValue,
nsAutoPtr<Expr> aFormat, nsAutoPtr<Expr> aGroupingSeparator,
nsAutoPtr<Expr> aGroupingSize);
TX_DECL_TXINSTRUCTION
txXSLTNumber::LevelType mLevel;
nsAutoPtr<txPattern> mCount;
nsAutoPtr<txPattern> mFrom;
nsAutoPtr<Expr> mValue;
nsAutoPtr<Expr> mFormat;
nsAutoPtr<Expr> mGroupingSeparator;
nsAutoPtr<Expr> mGroupingSize;
};
class txPopParams : public txInstruction
{
public:
TX_DECL_TXINSTRUCTION
};
class txProcessingInstruction : public txInstruction
{
public:
txProcessingInstruction(nsAutoPtr<Expr> aName);
TX_DECL_TXINSTRUCTION
nsAutoPtr<Expr> mName;
};
class txPushNewContext : public txInstruction
{
public:
txPushNewContext(nsAutoPtr<Expr> aSelect);
~txPushNewContext();
TX_DECL_TXINSTRUCTION
nsresult addSort(nsAutoPtr<Expr> aSelectExpr, nsAutoPtr<Expr> aLangExpr,
nsAutoPtr<Expr> aDataTypeExpr, nsAutoPtr<Expr> aOrderExpr,
nsAutoPtr<Expr> aCaseOrderExpr);
struct SortKey {
SortKey(nsAutoPtr<Expr> aSelectExpr, nsAutoPtr<Expr> aLangExpr,
nsAutoPtr<Expr> aDataTypeExpr, nsAutoPtr<Expr> aOrderExpr,
nsAutoPtr<Expr> aCaseOrderExpr);
nsAutoPtr<Expr> mSelectExpr;
nsAutoPtr<Expr> mLangExpr;
nsAutoPtr<Expr> mDataTypeExpr;
nsAutoPtr<Expr> mOrderExpr;
nsAutoPtr<Expr> mCaseOrderExpr;
};
nsVoidArray mSortKeys;
nsAutoPtr<Expr> 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<Expr> aValue);
TX_DECL_TXINSTRUCTION
txExpandedName mName;
nsAutoPtr<Expr> mValue;
};
class txSetVariable : public txInstruction
{
public:
txSetVariable(const txExpandedName& aName, nsAutoPtr<Expr> aValue);
TX_DECL_TXINSTRUCTION
txExpandedName mName;
nsAutoPtr<Expr> mValue;
};
class txStartElement : public txInstruction
{
public:
txStartElement(nsAutoPtr<Expr> aName, nsAutoPtr<Expr> aNamespace,
txNamespaceMap* aMappings);
TX_DECL_TXINSTRUCTION
nsAutoPtr<Expr> mName;
nsAutoPtr<Expr> mNamespace;
nsRefPtr<txNamespaceMap> mMappings;
};
class txStartLREElement : public txInstruction
{
public:
txStartLREElement(PRInt32 aNamespaceID, nsIAtom* aLocalName,
nsIAtom* aPrefix);
TX_DECL_TXINSTRUCTION
PRInt32 mNamespaceID;
nsCOMPtr<nsIAtom> mLocalName;
nsCOMPtr<nsIAtom> 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<Expr> aExpr, PRBool aDOE);
TX_DECL_TXINSTRUCTION
nsAutoPtr<Expr> mExpr;
PRBool mDOE;
};
#endif //TRANSFRMX_TXINSTRUCTIONS_H

View File

@ -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 <peterv@netscape.com> (original author)
*
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "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<txStylesheetCompiler> 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<txMozillaXSLTProcessor> mProcessor;
nsCOMPtr<nsILoadGroup> 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<nsIURI> uri;
nsresult rv = NS_NewURI(getter_AddRefs(uri), aUri);
NS_ENSURE_SUCCESS(rv, rv);
nsRefPtr<txStylesheetSink> 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<nsIChannel> channel;
nsresult rv = NS_NewChannel(getter_AddRefs(channel), aUri);
NS_ENSURE_SUCCESS(rv, rv);
channel->SetLoadGroup(mLoadGroup);
nsCOMPtr<nsIHttpChannel> 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<nsICharsetAlias> 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<nsIParser> parser = do_CreateInstance(kCParserCID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
// Set the parser as the stream listener for the document loader...
nsCOMPtr<nsIStreamListener> 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<txCompileObserver> observer =
new txCompileObserver(aProcessor, aLoadGroup);
NS_ENSURE_TRUE(observer, NS_ERROR_OUT_OF_MEMORY);
nsRefPtr<txStylesheetCompiler> compiler =
new txStylesheetCompiler(NS_ConvertUTF8toUCS2(uri), observer);
NS_ENSURE_TRUE(compiler, NS_ERROR_OUT_OF_MEMORY);
nsRefPtr<txStylesheetSink> 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<nsIContent> element = do_QueryInterface(aNode);
nsCOMPtr<nsINodeInfo> ni;
element->GetNodeInfo(*getter_AddRefs(ni));
PRInt32 namespaceID;
nsCOMPtr<nsIAtom> prefix, localname;
ni->GetNamespaceID(namespaceID);
ni->GetNameAtom(*getter_AddRefs(localname));
ni->GetPrefixAtom(*getter_AddRefs(prefix));
PRInt32 attsCount;
element->GetAttrCount(attsCount);
nsAutoArrayPtr<txStylesheetAttr> 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<nsIContent> child;
while (NS_SUCCEEDED(element->ChildAt(counter++, *getter_AddRefs(child))) && child) {
nsCOMPtr<nsIDOMNode> 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<nsIDocument> document = do_QueryInterface(aNode);
PRInt32 childCount;
document->GetChildCount(childCount);
if (childCount > 0) {
PRInt32 counter = 0;
nsCOMPtr<nsIContent> child;
while (NS_SUCCEEDED(document->ChildAt(counter++, *getter_AddRefs(child))) && child) {
nsCOMPtr<nsIDOMNode> 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<nsISyncLoadDOMService> mLoadService;
nsCOMPtr<nsIURI> 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<nsIURI> uri;
nsresult rv = NS_NewURI(getter_AddRefs(uri), aUri);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIChannel> 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<nsIHttpChannel> 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<nsIDOMDocument> 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<nsIDOMDocument> document;
aNode->GetOwnerDocument(getter_AddRefs(document));
if (!document) {
document = do_QueryInterface(aNode);
}
nsCOMPtr<nsIDocument> doc = do_QueryInterface(document);
nsCOMPtr<nsIURI> uri;
doc->GetBaseURL(*getter_AddRefs(uri));
nsCAutoString baseURI;
uri->GetSpec(baseURI);
nsRefPtr<txSyncCompileObserver> obs = new txSyncCompileObserver(uri);
NS_ENSURE_TRUE(obs, NS_ERROR_OUT_OF_MEMORY);
NS_ConvertUTF8toUCS2 base(baseURI);
nsRefPtr<txStylesheetCompiler> 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;
}

View File

@ -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<nsIDOMDocument> mSourceDocument;
nsCOMPtr<nsIDOMDocument> mResultDocument;
nsCOMPtr<nsITransformObserver> 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<nsIDOMDocument> 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<nsIDOMDocument> styleDOMDocument;
aStyleDOM->GetOwnerDocument(getter_AddRefs(styleDOMDocument));
if (!styleDOMDocument) {
styleDOMDocument = do_QueryInterface(aStyleDOM);
}
Document xslDocument(styleDOMDocument);
// Create a new ProcessorState. Must be done after creating the documents
// so that C++ will ensure that it is destroyed before the documents.
ProcessorState ps(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<nsIDOMDocument> styleDoc = do_QueryInterface(aStyleDOM);
nsresult rv;
if (styleDoc) {
rv = txXSLTProcessor::processStylesheet(&xslDocument,
&mVariables, &ps);
}
else {
nsCOMPtr<nsIDOMElement> styleElem = do_QueryInterface(aStyleDOM);
NS_ENSURE_TRUE(styleElem, NS_ERROR_FAILURE);
Element* element = xslDocument.createElement(styleElem);
NS_ENSURE_TRUE(element, NS_ERROR_OUT_OF_MEMORY);
rv = txXSLTProcessor::processTopLevel(element, &mVariables,
&ps);
}
NS_ENSURE_SUCCESS(rv, rv);
txToDocHandlerFactory handlerFactory(&ps, sourceDOMDocument, aOutputDoc,
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<nsIDOMDocument> 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<nsIDOMDocument> styleDOMDocument;
aStyleDOM->GetOwnerDocument(getter_AddRefs(styleDOMDocument));
if (!styleDOMDocument) {
styleDOMDocument = do_QueryInterface(aStyleDOM);
}
Document xslDocument(styleDOMDocument);
// Create a new ProcessorState. Must be done after creating the documents
// so that C++ will ensure that it is destroyed before the documents.
ProcessorState ps(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<nsIDOMDocument> styleDoc = do_QueryInterface(aStyleDOM);
nsresult rv;
if (styleDoc) {
rv = txXSLTProcessor::processStylesheet(&xslDocument,
&mVariables, &ps);
}
else {
nsCOMPtr<nsIDOMElement> styleElem = do_QueryInterface(aStyleDOM);
NS_ENSURE_TRUE(styleElem, NS_ERROR_FAILURE);
Element* element = xslDocument.createElement(styleElem);
NS_ENSURE_TRUE(element, NS_ERROR_OUT_OF_MEMORY);
rv = txXSLTProcessor::processTopLevel(element, &mVariables,
&ps);
}
NS_ENSURE_SUCCESS(rv, rv);
txToDocHandlerFactory handlerFactory(&ps, sourceDOMDocument, nsnull,
aObserver);
ps.mOutputHandlerFactory = &handlerFactory;
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<nsIDOMDocument> styleDoc = do_QueryInterface(mStylesheet);
nsresult rv;
if (styleDoc) {
rv = txXSLTProcessor::processStylesheet(&xslDocument,
&mVariables, &ps);
}
else {
nsCOMPtr<nsIDOMElement> styleElem = do_QueryInterface(mStylesheet);
NS_ENSURE_TRUE(styleElem, NS_ERROR_FAILURE);
Element* element = xslDocument.createElement(styleElem);
NS_ENSURE_TRUE(element, NS_ERROR_OUT_OF_MEMORY);
rv = txXSLTProcessor::processTopLevel(element, &mVariables,
&ps);
}
NS_ENSURE_SUCCESS(rv, rv);
txToDocHandlerFactory handlerFactory(&ps, sourceDOMDocument, nsnull,
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<nsIDOMDocument> styleDoc = do_QueryInterface(mStylesheet);
nsresult rv;
if (styleDoc) {
rv = txXSLTProcessor::processStylesheet(&xslDocument,
&mVariables, &ps);
}
else {
nsCOMPtr<nsIDOMElement> styleElem = do_QueryInterface(mStylesheet);
NS_ENSURE_TRUE(styleElem, NS_ERROR_FAILURE);
Element* element = xslDocument.createElement(styleElem);
NS_ENSURE_TRUE(element, NS_ERROR_OUT_OF_MEMORY);
rv = txXSLTProcessor::processTopLevel(element, &mVariables,
&ps);
}
NS_ENSURE_SUCCESS(rv, rv);
rv = aOutput->CreateDocumentFragment(aResult);
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)

View File

@ -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<nsIDOMNode> mStylesheet;
nsCOMPtr<nsIDOMDocument> mStylesheetDocument;
nsresult setStylesheet(txStylesheet* aStylesheet);
private:
nsresult DoTransform();
nsRefPtr<txStylesheet> mStylesheet;
nsCOMPtr<nsIDOMNode> mSource;
nsCOMPtr<nsITransformObserver> mObserver;
txExpandedNameMap mVariables;
};
extern nsresult TX_LoadSheet(nsIURI* aUri, txMozillaXSLTProcessor* aProcessor,
nsILoadGroup* aLoadGroup, nsIURI* aReferrerUri);
extern nsresult TX_CompileStylesheet(nsIDOMNode* aNode,
txStylesheet** aStylesheet);
#endif

View File

@ -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;
}

View File

@ -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,

View File

@ -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 <axel@pike.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "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<txStylesheetCompiler> 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<txDriver> 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<txDriver> driver = new txDriver();
if (!driver) {
return NS_ERROR_OUT_OF_MEMORY;
}
driver->mCompiler = aCompiler;
return driver->parse(*xslInput, aUri);
}

View File

@ -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 <axel@pike.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef __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__

View File

@ -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<txStylesheet> 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<txStylesheet> 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

View File

@ -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 <iostream.h>
#include <fstream.h>
@ -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:

View File

@ -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 <jonas@sicking.cc>
*
* 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<txNodeTest> nt(new txNodeTypeTest(txNodeTypeTest::NODE_TYPE));
NS_ENSURE_TRUE(nt, NS_ERROR_OUT_OF_MEMORY);
nsAutoPtr<Expr> 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<txDecimalFormat> 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<txList> 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<txPattern> 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<MatchableTemplate>
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<GlobalVariable> 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<txPattern> aMatch, nsAutoPtr<Expr> 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<txDecimalFormat> 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<Expr> aExpr,
nsAutoPtr<txInstruction> aFirstInstruction,
PRBool aIsParam)
: mExpr(aExpr), mFirstInstruction(aFirstInstruction), mIsParam(aIsParam)
{
}

View File

@ -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 <jonas@sicking.cc>
*
* 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<txPattern> aMatch,
nsAutoPtr<Expr> aUse);
/**
* Add a decimal-format to the stylesheet
*/
nsresult addDecimalFormat(const txExpandedName& aName,
nsAutoPtr<txDecimalFormat> 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<Expr> aExpr,
nsAutoPtr<txInstruction> aFirstInstruction,
PRBool aIsParam);
nsAutoPtr<Expr> mExpr;
nsAutoPtr<txInstruction> mFirstInstruction;
PRBool mIsParam;
};
private:
class MatchableTemplate {
public:
MatchableTemplate(txInstruction* aFirstInstruction,
nsAutoPtr<txPattern> aPattern,
double aPriority)
: mFirstInstruction(aFirstInstruction),
mMatch(aPattern),
mPriority(aPriority)
{
}
txInstruction* mFirstInstruction;
nsAutoPtr<txPattern> 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<txInstruction> mContainerTemplate;
nsAutoPtr<txInstruction> mCharactersTemplate;
nsAutoPtr<txInstruction> 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

File diff suppressed because it is too large Load Diff

View File

@ -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 <jonas@sicking.cc>
*
* 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

View File

@ -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 <jonas@sicking.cc>
*
* 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<txStylesheetAttr> 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<nsIAtom> 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<nsIAtom> 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<txInstruction> 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<txElementContext>
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<txInstruction> 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<txToplevelItem> 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<txStylesheetCompiler> 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<txStylesheetCompiler> 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;
}

View File

@ -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 <jonas@sicking.cc>
*
* 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<txNamespaceMap> 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<txInstruction> 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<txStylesheet> mStylesheet;
txHandlerTable* mHandlerTable;
nsAutoPtr<txElementContext> mElementContext;
txPushNewContext* mSorter;
nsAutoPtr<txList> mChooseGotoList;
PRPackedBool mDOE;
PRPackedBool mSearchingForFallback;
protected:
nsRefPtr<txACompileObserver> 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<nsIAtom> mLocalName;
nsCOMPtr<nsIAtom> 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

View File

@ -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)
{
}

View File

@ -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;
};

View File

@ -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 <jonas@sicking.cc>
*
* 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<txPattern> 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<Expr> aValue,
PRBool aIsParam)
: mName(aName), mValue(aValue), mIsParam(aIsParam)
{
}

View File

@ -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 <jonas@sicking.cc>
*
* 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<txInstruction> 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<txStylesheet::ImportFrame> 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<txPattern> aMatch, const txExpandedName& aName,
const txExpandedName& aMode, double aPrio);
TX_DECL_TOPLEVELITEM
nsAutoPtr<txPattern> mMatch;
txExpandedName mName;
txExpandedName mMode;
double mPrio;
};
// xsl:variable at top level
class txVariableItem : public txInstructionContainer
{
public:
txVariableItem(const txExpandedName& aName, nsAutoPtr<Expr> aValue,
PRBool aIsParam);
TX_DECL_TOPLEVELITEM
txExpandedName mName;
nsAutoPtr<Expr> mValue;
PRBool mIsParam;
};
#endif //TRANSFRMX_TXTOPLEVELITEMS_H

View File

@ -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);
}

View File

@ -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___ */

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -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");

View File

@ -40,9 +40,15 @@
#include "txAtoms.h"
#include "primitives.h"
#include <math.h>
#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<nsIAtom> 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;

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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 <jonas@sicking.cc>
*
* 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;
}

View File

@ -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 <jonas@sicking.cc>
*
* 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

View File

@ -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;

View File

@ -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

View File

@ -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) \