Fix for bug 73936 (xsl:include/xsl:import/document() doesn't work). r=Pike/sicking, sr=jst.

This commit is contained in:
peterv%netscape.com 2001-08-02 20:29:20 +00:00
Родитель c8136527c4
Коммит 62ef4ca538
20 изменённых файлов: 409 добавлений и 514 удалений

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

@ -107,6 +107,7 @@ public:
* Return the URL for the document. May return null.
*/
NS_IMETHOD GetDocumentURL(nsIURI** aURL) const = 0;
NS_IMETHOD SetDocumentURL(nsIURI* aURL) = 0;
/**
* Return the principal responsible for this document.

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

@ -682,7 +682,7 @@ nsDocument::Reset(nsIChannel* aChannel, nsILoadGroup* aLoadGroup)
return rv;
}
nsresult
NS_IMETHODIMP
nsDocument::SetDocumentURL(nsIURI* aURI)
{
NS_IF_RELEASE(mDocumentURL);

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

@ -516,7 +516,7 @@ public:
NS_IMETHOD_(PRBool) EventCaptureRegistration(PRInt32 aCapturerIncrement);
virtual nsresult SetDocumentURL(nsIURI* aURI);
NS_IMETHOD SetDocumentURL(nsIURI* aURI);
protected:
NS_IMETHOD GetDTD(nsIDTD** aDTD) const;

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

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
@ -24,23 +24,15 @@
*/
#include "nsSyncLoader.h"
#include "nsNetUtil.h"
#include "nsLayoutCID.h"
#include "nsIEventQueueService.h"
#include "nsAppShellCIDs.h"
#include "nsIDocument.h"
#include "nsIDOMDocument.h"
#include "nsIDOMDOMImplementation.h"
#include "nsIDOMEventReceiver.h"
#include "nsIXPConnect.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeItem.h"
#include "nsIScriptContext.h"
#include "nsIScriptGlobalObject.h"
#include "nsIDOMWindowInternal.h"
#include "nsAppShellCIDs.h"
#include "nsIAppShellService.h"
#include "nsIDocShellTreeOwner.h"
#include "nsIInterfaceRequestor.h"
#include "jsapi.h"
#include "nsIEventQueueService.h"
#include "nsIScriptSecurityManager.h"
#include "nsLayoutCID.h"
#include "nsNetUtil.h"
static const char* kLoadAsData = "loadAsData";
@ -98,7 +90,7 @@ txLoadListenerProxy::HandleEvent(nsIDOMEvent* aEvent)
if (listener) {
return listener->HandleEvent(aEvent);
}
return NS_OK;
}
@ -122,7 +114,7 @@ txLoadListenerProxy::Unload(nsIDOMEvent* aEvent)
if (listener) {
return listener->Unload(aEvent);
}
return NS_OK;
}
@ -134,7 +126,7 @@ txLoadListenerProxy::Abort(nsIDOMEvent* aEvent)
if (listener) {
return listener->Abort(aEvent);
}
return NS_OK;
}
@ -146,7 +138,7 @@ txLoadListenerProxy::Error(nsIDOMEvent* aEvent)
if (listener) {
return listener->Error(aEvent);
}
return NS_OK;
}
@ -157,177 +149,147 @@ nsSyncLoader::nsSyncLoader()
nsSyncLoader::~nsSyncLoader()
{
//if (XML_HTTP_REQUEST_SENT == mStatus) {
// Abort();
//}
if (mChromeWindow)
mChromeWindow->ExitModalEventLoop(NS_OK);
if (mLoading && mChannel) {
mChannel->Cancel(NS_BINDING_ABORTED);
}
}
NS_IMPL_ISUPPORTS3(nsSyncLoader, nsISyncLoader, nsIDOMLoadListener, nsISupportsWeakReference)
NS_IMETHODIMP
nsSyncLoader::LoadDocument(nsIURI* documentURI, nsIDOMDocument **_retval)
nsSyncLoader::LoadDocument(nsIURI* documentURI, nsIDocument *aLoader, nsIDOMDocument **_retval)
{
nsresult rv = NS_OK;
nsCOMPtr<nsIURI> loaderURI;
aLoader->GetDocumentURL(getter_AddRefs(loaderURI));
nsCOMPtr<nsIScriptSecurityManager> securityManager =
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = securityManager->CheckLoadURI(loaderURI, documentURI,
nsIScriptSecurityManager::STANDARD);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsILoadGroup> loadGroup;
// If we have a base document, use it for the base URL and loadgroup
//if (mBaseDocument) {
// rv = mBaseDocument->GetDocumentLoadGroup(getter_AddRefs(loadGroup));
// if (NS_FAILED(rv)) return rv;
//}
//rv = NS_NewURI(getter_AddRefs(uri), url, mBaseURI);
//if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIChannel> channel;
rv = NS_OpenURI(getter_AddRefs(channel), documentURI, nsnull, loadGroup);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIInputStream> postDataStream;
// Make sure we've been opened
if (!channel) {
return NS_ERROR_NOT_INITIALIZED;
}
rv = aLoader->GetDocumentLoadGroup(getter_AddRefs(loadGroup));
NS_ENSURE_SUCCESS(rv, rv);
// Get and initialize a DOMImplementation
nsCOMPtr<nsIDOMDOMImplementation> implementation = do_CreateInstance(kIDOMDOMImplementationCID, &rv);
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
//if (mBaseURI) {
// nsCOMPtr<nsIPrivateDOMImplementation> privImpl = do_QueryInterface(implementation);
// if (privImpl) {
// privImpl->Init(mBaseURI);
// }
//}
nsCOMPtr<nsIDOMDOMImplementation> implementation =
do_CreateInstance(kIDOMDOMImplementationCID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
// Create an empty document from it
nsAutoString emptyStr;
nsString emptyStr;
nsCOMPtr<nsIDOMDocument> DOMDocument;
rv = implementation->CreateDocument(emptyStr,
emptyStr,
nsnull,
getter_AddRefs(DOMDocument));
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
NS_ENSURE_SUCCESS(rv, rv);
rv = NS_OpenURI(getter_AddRefs(mChannel), documentURI, nsnull, loadGroup);
NS_ENSURE_SUCCESS(rv, rv);
// Make sure we've been opened
if (!mChannel) {
return NS_ERROR_NOT_INITIALIZED;
}
// Tell the document to start loading
nsCOMPtr<nsIDocument> document = do_QueryInterface(DOMDocument, &rv);
NS_ENSURE_SUCCESS(rv, rv);
// Partial Reset
document->SetDocumentURL(documentURI);
document->SetBaseURL(documentURI);
document->SetBaseTarget(NS_LITERAL_STRING(""));
nsCOMPtr<nsIEventQueueService> service =
do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIEventQueue> currentThreadQ;
rv = service->PushThreadEventQueue(getter_AddRefs(currentThreadQ));
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
// Register as a load listener on the document
nsCOMPtr<nsIDOMEventReceiver> target = do_QueryInterface(DOMDocument);
txLoadListenerProxy* proxy;
if (target) {
nsWeakPtr requestWeak = getter_AddRefs(NS_GetWeakReference(NS_STATIC_CAST(nsIDOMLoadListener*, this)));
txLoadListenerProxy* proxy = new txLoadListenerProxy(requestWeak);
if (!proxy) return NS_ERROR_OUT_OF_MEMORY;
proxy = new txLoadListenerProxy(requestWeak);
if (!proxy) {
service->PopThreadEventQueue(currentThreadQ);
return NS_ERROR_OUT_OF_MEMORY;
}
// This will addref the proxy
rv = target->AddEventListenerByIID(NS_STATIC_CAST(nsIDOMEventListener*,
proxy),
NS_GET_IID(nsIDOMLoadListener));
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
}
// Tell the document to start loading
nsCOMPtr<nsIStreamListener> listener;
nsCOMPtr<nsIDocument> document = do_QueryInterface(DOMDocument);
if (!document) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIEventQueue> modalEventQueue;
nsCOMPtr<nsIEventQueueService> eventQService;
nsCOMPtr<nsIXPCNativeCallContext> cc;
nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
if(NS_SUCCEEDED(rv)) {
rv = xpc->GetCurrentNativeCallContext(getter_AddRefs(cc));
}
JSContext* cx;
if (NS_SUCCEEDED(rv) && cc) {
rv = cc->GetJSContext(&cx);
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
}
else {
nsCOMPtr<nsIAppShellService> appshellSvc =
do_GetService(kAppShellServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIDOMWindowInternal> junk;
rv = appshellSvc->GetHiddenWindowAndJSContext(getter_AddRefs(junk), &cx);
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
}
if (NS_SUCCEEDED(rv)) {
nsIScriptContext* scriptCX;
// We can only do this if we're called from a DOM script context
scriptCX = (nsIScriptContext*)JS_GetContextPrivate(cx);
if (!scriptCX) return NS_OK;
// Get the nsIDocShellTreeOwner associated with the window
// containing this script context
// XXX Need to find a better way to do this rather than
// chaining through a bunch of getters and QIs
nsCOMPtr<nsIScriptGlobalObject> global;
scriptCX->GetGlobalObject(getter_AddRefs(global));
if (!global) return NS_ERROR_FAILURE;
nsCOMPtr<nsIDocShell> docshell;
rv = global->GetDocShell(getter_AddRefs(docshell));
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
nsCOMPtr<nsIDocShellTreeItem> item = do_QueryInterface(docshell);
if (!item) return NS_ERROR_FAILURE;
nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
rv = item->GetTreeOwner(getter_AddRefs(treeOwner));
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
nsCOMPtr<nsIInterfaceRequestor> treeRequestor(do_GetInterface(treeOwner));
if (!treeRequestor) return NS_ERROR_FAILURE;
treeRequestor->GetInterface(NS_GET_IID(nsIWebBrowserChrome), getter_AddRefs(mChromeWindow));
if (mChromeWindow) return NS_ERROR_FAILURE;
eventQService = do_GetService(kEventQueueServiceCID);
if(!eventQService ||
NS_FAILED(eventQService->PushThreadEventQueue(getter_AddRefs(modalEventQueue)))) {
return NS_ERROR_FAILURE;
NS_GET_IID(nsIDOMLoadListener));
if (NS_FAILED(rv)) {
service->PopThreadEventQueue(currentThreadQ);
return rv;
}
}
mLoadSuccess = PR_FALSE;
rv = document->StartDocumentLoad(kLoadAsData, channel,
nsnull, nsnull,
nsCOMPtr<nsIStreamListener> listener;
rv = document->StartDocumentLoad(kLoadAsData, mChannel,
loadGroup, nsnull,
getter_AddRefs(listener),
PR_FALSE);
if (NS_FAILED(rv)) {
if (modalEventQueue) {
eventQService->PopThreadEventQueue(modalEventQueue);
if (NS_SUCCEEDED(rv)) {
// Start reading from the channel
rv = mChannel->AsyncOpen(listener, nsnull);
if (NS_SUCCEEDED(rv)) {
mLoading = PR_TRUE;
// process events until we're finished.
PLEvent *event;
while (mLoading && NS_SUCCEEDED(rv)) {
rv = currentThreadQ->WaitForEvent(&event);
NS_ASSERTION(NS_SUCCEEDED(rv), ": currentThreadQ->WaitForEvent failed...\n");
if (NS_SUCCEEDED(rv)) {
rv = currentThreadQ->HandleEvent(event);
NS_ASSERTION(NS_SUCCEEDED(rv), ": currentThreadQ->HandleEvent failed...\n");
}
}
}
return NS_ERROR_FAILURE;
}
// Start reading from the channel
rv = channel->AsyncOpen(listener, nsnull);
mChannel = 0;
if (NS_FAILED(rv)) {
if (modalEventQueue) {
eventQService->PopThreadEventQueue(modalEventQueue);
}
return NS_ERROR_FAILURE;
}
// Spin an event loop here and wait
if (mChromeWindow) {
rv = mChromeWindow->ShowAsModal();
eventQService->PopThreadEventQueue(modalEventQueue);
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
service->PopThreadEventQueue(currentThreadQ);
// This will release the proxy
target->RemoveEventListenerByIID(NS_STATIC_CAST(nsIDOMEventListener*,
proxy),
NS_GET_IID(nsIDOMLoadListener));
return rv;
}
*_retval = DOMDocument;
NS_ADDREF(*_retval);
// This will release the proxy
rv = target->RemoveEventListenerByIID(NS_STATIC_CAST(nsIDOMEventListener*,
proxy),
NS_GET_IID(nsIDOMLoadListener));
if (NS_FAILED(rv)) {
return rv;
}
if (mLoadSuccess) {
*_retval = DOMDocument;
NS_ADDREF(*_retval);
}
rv = service->PopThreadEventQueue(currentThreadQ);
return rv;
}
@ -342,9 +304,9 @@ nsSyncLoader::HandleEvent(nsIDOMEvent* aEvent)
nsresult
nsSyncLoader::Load(nsIDOMEvent* aEvent)
{
if (mChromeWindow) {
mChromeWindow->ExitModalEventLoop(NS_OK);
mChromeWindow = 0;
if (mLoading) {
mLoading = PR_FALSE;
mLoadSuccess = PR_TRUE;
}
return NS_OK;
@ -359,9 +321,8 @@ nsSyncLoader::Unload(nsIDOMEvent* aEvent)
nsresult
nsSyncLoader::Abort(nsIDOMEvent* aEvent)
{
if (mChromeWindow) {
mChromeWindow->ExitModalEventLoop(NS_OK);
mChromeWindow = 0;
if (mLoading) {
mLoading = PR_FALSE;
}
return NS_OK;
@ -370,9 +331,8 @@ nsSyncLoader::Abort(nsIDOMEvent* aEvent)
nsresult
nsSyncLoader::Error(nsIDOMEvent* aEvent)
{
if (mChromeWindow) {
mChromeWindow->ExitModalEventLoop(NS_OK);
mChromeWindow = 0;
if (mLoading) {
mLoading = PR_FALSE;
}
return NS_OK;

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

@ -110,11 +110,6 @@ public:
*/
NS_IMETHOD SetCurrentPrototype(nsIXULPrototypeDocument* aDocument) = 0;
/**
* Set the doc's URL
*/
NS_IMETHOD SetDocumentURL(nsIURI* aURI) = 0;
/**
* Load inline and attribute style sheets
*/

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

@ -26,6 +26,7 @@
#include "nsISupports.idl"
interface nsIURI;
interface nsIDocument;
interface nsIDOMDocument;
/**
@ -40,10 +41,11 @@ interface nsISyncLoader : nsISupports {
* Synchronously load the document specified in documentURI.
*
* @param documentURI The URI of the document to load.
* @param aLoader The document that is trying to load this document.
*
* @returns The document loaded from the URI.
*/
nsIDOMDocument loadDocument(in nsIURI aDocumentURI);
nsIDOMDocument loadDocument(in nsIURI aDocumentURI, in nsIDocument aLoader);
};
%{ C++

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

@ -1,4 +1,5 @@
/*
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
@ -26,19 +27,13 @@
* URIUtils.cpp to here
*
* Peter Van der Beken
* -- 20000326
* -- added Mozilla integration code
*
*/
#include "URIUtils.h"
#ifndef TX_EXE
#include "nsIServiceManager.h"
#include "nsIIOService.h"
#include "nsIURL.h"
#include "nsXPIDLString.h"
#include "nsNetCID.h"
#include "nsNetUtil.h"
#endif
/**
@ -151,29 +146,24 @@ void URIUtils::getDocumentBase(const String& href, String& dest) {
* if necessary.
* The new resolved href will be appended to the given dest String
**/
void URIUtils::resolveHref(const String& href, const String& base, String& dest) {
void URIUtils::resolveHref(const String& href, const String& base,
String& dest) {
if (base.length() == 0) {
dest.append(href);
return;
}
if (href.length() == 0) {
dest.append(base);
return;
}
#ifndef TX_EXE
nsCOMPtr<nsIURI> pURL;
nsresult result = NS_OK;
nsCOMPtr<nsIIOService> pService(do_GetService(NS_IOSERVICE_CONTRACTID,
&result));
String resultHref;
nsresult result = NS_NewURI(getter_AddRefs(pURL), base.getConstNSString());
if (NS_SUCCEEDED(result)) {
// XXX This is ugly, there must be an easier (cleaner way).
char *baseStr = (base.getConstNSString()).ToNewCString();
result = pService->NewURI(baseStr, nsnull, getter_AddRefs(pURL));
nsCRT::free(baseStr);
if (NS_SUCCEEDED(result)) {
nsXPIDLCString newURL;
// XXX This is ugly, there must be an easier (cleaner way).
char *hrefStr = (href.getConstNSString()).ToNewCString();
result = pURL->Resolve(hrefStr, getter_Copies(newURL));
nsCRT::free(hrefStr);
if (NS_SUCCEEDED(result)) {
dest = (const char *)newURL;
}
}
NS_MakeAbsoluteURI(resultHref.getNSString(), href.getConstNSString(), pURL);
dest.append(resultHref);
}
#else
String documentBase;
@ -233,7 +223,7 @@ void URIUtils::getDocumentURI(const String& href, String& docUri) {
href.subString(0,pos,docUri);
else
docUri = href;
} //-- getFragmentIdentifier
} //-- getDocumentURI
#ifdef TX_EXE
istream* URIUtils::openStream(ParsedURI* uri) {

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

@ -623,24 +623,3 @@ TxObject* Document::removeWrapper(MozillaObjectWrapper* aObject)
nsISupportsKey key(aObject->getNSObj());
return (TxObject*)wrapperHashTable->Remove(&key);
}
String Document::getBaseURI()
{
NSI_FROM_TX(Document)
String url;
nsIURI* docURL = nsnull;
nsCOMPtr<nsIDocument> sourceNsDocument(do_QueryInterface(nsDocument));
if (sourceNsDocument)
sourceNsDocument->GetBaseURL(docURL);
if (docURL) {
char* urlString;
docURL->GetSpec(&urlString);
url = urlString;
nsCRT::free(urlString);
NS_IF_RELEASE(docURL);
}
return url;
}

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

@ -27,10 +27,7 @@
*/
#include "mozilladom.h"
#include "ArrayList.h"
#include "URIUtils.h"
const String XMLBASE_ATTR = "xml:base";
MOZ_DECL_CTOR_COUNTER(Node)
/**
@ -384,40 +381,12 @@ MBool Node::hasChildNodes() const
**/
String Node::getBaseURI()
{
Node* node=this;
ArrayList baseUrls;
NSI_FROM_TX(Node)
nsCOMPtr<nsIDOM3Node> nsDOM3Node = do_QueryInterface(nsNode);
String url;
Node* xbAttr;
while(node) {
switch(node->getNodeType()) {
case Node::ELEMENT_NODE :
xbAttr = ((Element*)node)->getAttributeNode(XMLBASE_ATTR);
if(xbAttr)
baseUrls.add(new String(xbAttr->getNodeValue()));
break;
case Node::DOCUMENT_NODE :
baseUrls.add(new String(((Document*)node)->getBaseURI()));
break;
default:
break;
}
node = node->getParentNode();
}
if(baseUrls.size()) {
url = *((String*)baseUrls.get(baseUrls.size()-1));
for(int i=baseUrls.size()-2;i>=0;i--) {
String dest;
URIUtils::resolveHref(*(String*)baseUrls.get(i), url, dest);
url = dest;
}
}
baseUrls.clear(MB_TRUE);
if (nsDOM3Node)
nsDOM3Node->GetBaseURI(url.getNSString());
return url;
}

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

@ -366,9 +366,6 @@ class Document : public Node
Element* getElementById(const String aID);
//Override to return documentBaseURI
String getBaseURI();
private:
PRBool bInHashTableDeletion;

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

@ -37,14 +37,12 @@
*/
#include "XMLParser.h"
#include "URIUtils.h"
#ifndef TX_EXE
#include "nsSyncLoader.h"
#include "URIUtils.h"
#include "nsIIOService.h"
#include "nsIURL.h"
#include "nsNetCID.h"
#include "nsIServiceManager.h"
#include "nsNetUtil.h"
#endif
/**
* Implementation of an In-Memory DOM based XML parser. The actual XML
* parsing is provided by EXPAT.
@ -66,31 +64,31 @@ XMLParser::~XMLParser()
//-- clean up
} //-- ~XMLParser
Document* XMLParser::getDocumentFromURI
(const String& href, const String& baseUri, String& errMsg)
Document* XMLParser::getDocumentFromURI(const String& href,
const String& baseUri,
Document* aLoader,
String& errMsg)
{
String documentURL;
URIUtils::resolveHref(href, baseUri, documentURL);
#ifndef TX_EXE
nsresult rv = NS_OK;
nsCOMPtr<nsIURI> documentURI;
nsCOMPtr<nsIIOService> pService(do_GetService(NS_IOSERVICE_CONTRACTID,
&rv));
if (NS_FAILED(rv)) return NULL;
nsresult rv = NS_NewURI(getter_AddRefs(documentURI), documentURL.getConstNSString());
NS_ENSURE_SUCCESS(rv, NULL);
char *hrefStr = (documentURL.getConstNSString()).ToNewCString();
rv = pService->NewURI(hrefStr, nsnull, getter_AddRefs(documentURI));
nsCRT::free(hrefStr);
if (NS_FAILED(rv)) return NULL;
nsCOMPtr<nsISyncLoader> loader = do_CreateInstance(TRANSFORMIIX_SYNCLOADER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, NULL);
nsCOMPtr<nsISyncLoader>aLoader = do_CreateInstance( TRANSFORMIIX_SYNCLOADER_CONTRACTID, &rv );
if (NS_FAILED(rv)) return NULL;
nsCOMPtr <nsIDOMDocument> theDocument;
rv = aLoader->LoadDocument(documentURI, getter_AddRefs(theDocument));
if (NS_FAILED(rv)) return NULL;
nsCOMPtr<nsIDOMDocument> theDocument;
nsCOMPtr<nsIDocument> loaderDocument = do_QueryInterface(aLoader->getNSObj());
rv = loader->LoadDocument(documentURI, loaderDocument, getter_AddRefs(theDocument));
if (NS_FAILED(rv) || !theDocument) {
errMsg.append("Document load of ");
errMsg.append(href);
errMsg.append(" failed.");
return NULL;
}
return new Document(theDocument);
#else

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

@ -28,20 +28,21 @@
#ifndef MITRE_XMLPARSER_H
#define MITRE_XMLPARSER_H
#include <iostream.h>
#include "dom.h"
#ifdef TX_EXE
#ifndef XML_UNICODE
#define XML_UNICODE
#endif
#ifdef TX_EXE
#include "xmlparse.h"
#include "URIUtils.h"
#endif
#include "dom.h"
#include <iostream.h>
typedef struct {
Document* document;
Node* currentNode;
} ParserState;
#endif
/**
* Implementation of an In-Memory DOM based XML parser. The actual XML
@ -66,7 +67,7 @@ class XMLParser
XMLParser();
~XMLParser();
Document* getDocumentFromURI(const String& href, const String& baseUri, String& errMsg);
Document* getDocumentFromURI(const String& href, const String& baseUri, Document* aLoader, String& errMsg);
#ifdef TX_EXE
Document* parse(istream& inputStream, const String& uri);
const String& getErrorString();

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

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
@ -24,23 +24,15 @@
*/
#include "nsSyncLoader.h"
#include "nsNetUtil.h"
#include "nsLayoutCID.h"
#include "nsIEventQueueService.h"
#include "nsAppShellCIDs.h"
#include "nsIDocument.h"
#include "nsIDOMDocument.h"
#include "nsIDOMDOMImplementation.h"
#include "nsIDOMEventReceiver.h"
#include "nsIXPConnect.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeItem.h"
#include "nsIScriptContext.h"
#include "nsIScriptGlobalObject.h"
#include "nsIDOMWindowInternal.h"
#include "nsAppShellCIDs.h"
#include "nsIAppShellService.h"
#include "nsIDocShellTreeOwner.h"
#include "nsIInterfaceRequestor.h"
#include "jsapi.h"
#include "nsIEventQueueService.h"
#include "nsIScriptSecurityManager.h"
#include "nsLayoutCID.h"
#include "nsNetUtil.h"
static const char* kLoadAsData = "loadAsData";
@ -98,7 +90,7 @@ txLoadListenerProxy::HandleEvent(nsIDOMEvent* aEvent)
if (listener) {
return listener->HandleEvent(aEvent);
}
return NS_OK;
}
@ -122,7 +114,7 @@ txLoadListenerProxy::Unload(nsIDOMEvent* aEvent)
if (listener) {
return listener->Unload(aEvent);
}
return NS_OK;
}
@ -134,7 +126,7 @@ txLoadListenerProxy::Abort(nsIDOMEvent* aEvent)
if (listener) {
return listener->Abort(aEvent);
}
return NS_OK;
}
@ -146,7 +138,7 @@ txLoadListenerProxy::Error(nsIDOMEvent* aEvent)
if (listener) {
return listener->Error(aEvent);
}
return NS_OK;
}
@ -157,177 +149,147 @@ nsSyncLoader::nsSyncLoader()
nsSyncLoader::~nsSyncLoader()
{
//if (XML_HTTP_REQUEST_SENT == mStatus) {
// Abort();
//}
if (mChromeWindow)
mChromeWindow->ExitModalEventLoop(NS_OK);
if (mLoading && mChannel) {
mChannel->Cancel(NS_BINDING_ABORTED);
}
}
NS_IMPL_ISUPPORTS3(nsSyncLoader, nsISyncLoader, nsIDOMLoadListener, nsISupportsWeakReference)
NS_IMETHODIMP
nsSyncLoader::LoadDocument(nsIURI* documentURI, nsIDOMDocument **_retval)
nsSyncLoader::LoadDocument(nsIURI* documentURI, nsIDocument *aLoader, nsIDOMDocument **_retval)
{
nsresult rv = NS_OK;
nsCOMPtr<nsIURI> loaderURI;
aLoader->GetDocumentURL(getter_AddRefs(loaderURI));
nsCOMPtr<nsIScriptSecurityManager> securityManager =
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = securityManager->CheckLoadURI(loaderURI, documentURI,
nsIScriptSecurityManager::STANDARD);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsILoadGroup> loadGroup;
// If we have a base document, use it for the base URL and loadgroup
//if (mBaseDocument) {
// rv = mBaseDocument->GetDocumentLoadGroup(getter_AddRefs(loadGroup));
// if (NS_FAILED(rv)) return rv;
//}
//rv = NS_NewURI(getter_AddRefs(uri), url, mBaseURI);
//if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIChannel> channel;
rv = NS_OpenURI(getter_AddRefs(channel), documentURI, nsnull, loadGroup);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIInputStream> postDataStream;
// Make sure we've been opened
if (!channel) {
return NS_ERROR_NOT_INITIALIZED;
}
rv = aLoader->GetDocumentLoadGroup(getter_AddRefs(loadGroup));
NS_ENSURE_SUCCESS(rv, rv);
// Get and initialize a DOMImplementation
nsCOMPtr<nsIDOMDOMImplementation> implementation = do_CreateInstance(kIDOMDOMImplementationCID, &rv);
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
//if (mBaseURI) {
// nsCOMPtr<nsIPrivateDOMImplementation> privImpl = do_QueryInterface(implementation);
// if (privImpl) {
// privImpl->Init(mBaseURI);
// }
//}
nsCOMPtr<nsIDOMDOMImplementation> implementation =
do_CreateInstance(kIDOMDOMImplementationCID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
// Create an empty document from it
nsAutoString emptyStr;
nsString emptyStr;
nsCOMPtr<nsIDOMDocument> DOMDocument;
rv = implementation->CreateDocument(emptyStr,
emptyStr,
nsnull,
getter_AddRefs(DOMDocument));
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
NS_ENSURE_SUCCESS(rv, rv);
rv = NS_OpenURI(getter_AddRefs(mChannel), documentURI, nsnull, loadGroup);
NS_ENSURE_SUCCESS(rv, rv);
// Make sure we've been opened
if (!mChannel) {
return NS_ERROR_NOT_INITIALIZED;
}
// Tell the document to start loading
nsCOMPtr<nsIDocument> document = do_QueryInterface(DOMDocument, &rv);
NS_ENSURE_SUCCESS(rv, rv);
// Partial Reset
document->SetDocumentURL(documentURI);
document->SetBaseURL(documentURI);
document->SetBaseTarget(NS_LITERAL_STRING(""));
nsCOMPtr<nsIEventQueueService> service =
do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIEventQueue> currentThreadQ;
rv = service->PushThreadEventQueue(getter_AddRefs(currentThreadQ));
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
// Register as a load listener on the document
nsCOMPtr<nsIDOMEventReceiver> target = do_QueryInterface(DOMDocument);
txLoadListenerProxy* proxy;
if (target) {
nsWeakPtr requestWeak = getter_AddRefs(NS_GetWeakReference(NS_STATIC_CAST(nsIDOMLoadListener*, this)));
txLoadListenerProxy* proxy = new txLoadListenerProxy(requestWeak);
if (!proxy) return NS_ERROR_OUT_OF_MEMORY;
proxy = new txLoadListenerProxy(requestWeak);
if (!proxy) {
service->PopThreadEventQueue(currentThreadQ);
return NS_ERROR_OUT_OF_MEMORY;
}
// This will addref the proxy
rv = target->AddEventListenerByIID(NS_STATIC_CAST(nsIDOMEventListener*,
proxy),
NS_GET_IID(nsIDOMLoadListener));
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
}
// Tell the document to start loading
nsCOMPtr<nsIStreamListener> listener;
nsCOMPtr<nsIDocument> document = do_QueryInterface(DOMDocument);
if (!document) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIEventQueue> modalEventQueue;
nsCOMPtr<nsIEventQueueService> eventQService;
nsCOMPtr<nsIXPCNativeCallContext> cc;
nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
if(NS_SUCCEEDED(rv)) {
rv = xpc->GetCurrentNativeCallContext(getter_AddRefs(cc));
}
JSContext* cx;
if (NS_SUCCEEDED(rv) && cc) {
rv = cc->GetJSContext(&cx);
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
}
else {
nsCOMPtr<nsIAppShellService> appshellSvc =
do_GetService(kAppShellServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIDOMWindowInternal> junk;
rv = appshellSvc->GetHiddenWindowAndJSContext(getter_AddRefs(junk), &cx);
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
}
if (NS_SUCCEEDED(rv)) {
nsIScriptContext* scriptCX;
// We can only do this if we're called from a DOM script context
scriptCX = (nsIScriptContext*)JS_GetContextPrivate(cx);
if (!scriptCX) return NS_OK;
// Get the nsIDocShellTreeOwner associated with the window
// containing this script context
// XXX Need to find a better way to do this rather than
// chaining through a bunch of getters and QIs
nsCOMPtr<nsIScriptGlobalObject> global;
scriptCX->GetGlobalObject(getter_AddRefs(global));
if (!global) return NS_ERROR_FAILURE;
nsCOMPtr<nsIDocShell> docshell;
rv = global->GetDocShell(getter_AddRefs(docshell));
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
nsCOMPtr<nsIDocShellTreeItem> item = do_QueryInterface(docshell);
if (!item) return NS_ERROR_FAILURE;
nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
rv = item->GetTreeOwner(getter_AddRefs(treeOwner));
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
nsCOMPtr<nsIInterfaceRequestor> treeRequestor(do_GetInterface(treeOwner));
if (!treeRequestor) return NS_ERROR_FAILURE;
treeRequestor->GetInterface(NS_GET_IID(nsIWebBrowserChrome), getter_AddRefs(mChromeWindow));
if (mChromeWindow) return NS_ERROR_FAILURE;
eventQService = do_GetService(kEventQueueServiceCID);
if(!eventQService ||
NS_FAILED(eventQService->PushThreadEventQueue(getter_AddRefs(modalEventQueue)))) {
return NS_ERROR_FAILURE;
NS_GET_IID(nsIDOMLoadListener));
if (NS_FAILED(rv)) {
service->PopThreadEventQueue(currentThreadQ);
return rv;
}
}
mLoadSuccess = PR_FALSE;
rv = document->StartDocumentLoad(kLoadAsData, channel,
nsnull, nsnull,
nsCOMPtr<nsIStreamListener> listener;
rv = document->StartDocumentLoad(kLoadAsData, mChannel,
loadGroup, nsnull,
getter_AddRefs(listener),
PR_FALSE);
if (NS_FAILED(rv)) {
if (modalEventQueue) {
eventQService->PopThreadEventQueue(modalEventQueue);
if (NS_SUCCEEDED(rv)) {
// Start reading from the channel
rv = mChannel->AsyncOpen(listener, nsnull);
if (NS_SUCCEEDED(rv)) {
mLoading = PR_TRUE;
// process events until we're finished.
PLEvent *event;
while (mLoading && NS_SUCCEEDED(rv)) {
rv = currentThreadQ->WaitForEvent(&event);
NS_ASSERTION(NS_SUCCEEDED(rv), ": currentThreadQ->WaitForEvent failed...\n");
if (NS_SUCCEEDED(rv)) {
rv = currentThreadQ->HandleEvent(event);
NS_ASSERTION(NS_SUCCEEDED(rv), ": currentThreadQ->HandleEvent failed...\n");
}
}
}
return NS_ERROR_FAILURE;
}
// Start reading from the channel
rv = channel->AsyncOpen(listener, nsnull);
mChannel = 0;
if (NS_FAILED(rv)) {
if (modalEventQueue) {
eventQService->PopThreadEventQueue(modalEventQueue);
}
return NS_ERROR_FAILURE;
}
// Spin an event loop here and wait
if (mChromeWindow) {
rv = mChromeWindow->ShowAsModal();
eventQService->PopThreadEventQueue(modalEventQueue);
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
service->PopThreadEventQueue(currentThreadQ);
// This will release the proxy
target->RemoveEventListenerByIID(NS_STATIC_CAST(nsIDOMEventListener*,
proxy),
NS_GET_IID(nsIDOMLoadListener));
return rv;
}
*_retval = DOMDocument;
NS_ADDREF(*_retval);
// This will release the proxy
rv = target->RemoveEventListenerByIID(NS_STATIC_CAST(nsIDOMEventListener*,
proxy),
NS_GET_IID(nsIDOMLoadListener));
if (NS_FAILED(rv)) {
return rv;
}
if (mLoadSuccess) {
*_retval = DOMDocument;
NS_ADDREF(*_retval);
}
rv = service->PopThreadEventQueue(currentThreadQ);
return rv;
}
@ -342,9 +304,9 @@ nsSyncLoader::HandleEvent(nsIDOMEvent* aEvent)
nsresult
nsSyncLoader::Load(nsIDOMEvent* aEvent)
{
if (mChromeWindow) {
mChromeWindow->ExitModalEventLoop(NS_OK);
mChromeWindow = 0;
if (mLoading) {
mLoading = PR_FALSE;
mLoadSuccess = PR_TRUE;
}
return NS_OK;
@ -359,9 +321,8 @@ nsSyncLoader::Unload(nsIDOMEvent* aEvent)
nsresult
nsSyncLoader::Abort(nsIDOMEvent* aEvent)
{
if (mChromeWindow) {
mChromeWindow->ExitModalEventLoop(NS_OK);
mChromeWindow = 0;
if (mLoading) {
mLoading = PR_FALSE;
}
return NS_OK;
@ -370,9 +331,8 @@ nsSyncLoader::Abort(nsIDOMEvent* aEvent)
nsresult
nsSyncLoader::Error(nsIDOMEvent* aEvent)
{
if (mChromeWindow) {
mChromeWindow->ExitModalEventLoop(NS_OK);
mChromeWindow = 0;
if (mLoading) {
mLoading = PR_FALSE;
}
return NS_OK;

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

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
@ -27,12 +27,11 @@
#define nsSyncLoader_h__
#include "nsCOMPtr.h"
#include "nsString.h"
#include "nsIChannel.h"
#include "nsIDOMLoadListener.h"
#include "nsIDocument.h"
#include "nsIWebBrowserChrome.h"
#include "nsWeakReference.h"
#include "nsISyncLoader.h"
#include "nsString.h"
#include "nsWeakReference.h"
class nsSyncLoader : public nsISyncLoader,
public nsIDOMLoadListener,
@ -56,7 +55,8 @@ public:
NS_IMETHOD Error(nsIDOMEvent* aEvent);
protected:
nsCOMPtr<nsIWebBrowserChrome> mChromeWindow;
nsCOMPtr<nsIChannel> mChannel;
PRBool mLoading, mLoadSuccess;
};
#endif

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

@ -36,7 +36,6 @@
#include "TxString.h"
#include "primitives.h"
#include "ExprResult.h"
#include "baseutils.h"
#include "Expr.h"

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

@ -61,6 +61,7 @@ const String ProcessorState::wrapperNS = "http://www.mitre.org/TransforMi
* Creates a new ProcessorState
**/
ProcessorState::ProcessorState() {
this->mSourceDocument = NULL;
this->xslDocument = NULL;
this->resultDocument = NULL;
currentAction = 0;
@ -71,7 +72,8 @@ ProcessorState::ProcessorState() {
* Creates a new ProcessorState for the given XSL document
* and resultDocument
**/
ProcessorState::ProcessorState(Document& xslDocument, Document& resultDocument) {
ProcessorState::ProcessorState(Document& sourceDocument, Document& xslDocument, Document& resultDocument) {
this->mSourceDocument = &sourceDocument;
this->xslDocument = &xslDocument;
this->resultDocument = &resultDocument;
currentAction = 0;
@ -550,6 +552,17 @@ MBool ProcessorState::isXSLStripSpaceAllowed(Node* node) {
} //--isXSLStripSpaceAllowed
/**
* Returns the current XSLT action from the top of the stack.
* @returns the XSLT action from the top of the stack
**/
Node* ProcessorState::peekAction() {
NS_ASSERTION(currentAction, "currentAction is NULL, this is very bad");
if (currentAction)
return currentAction->node;
return NULL;
}
/**
* Removes the current XSLT action from the top of the stack.
* @returns the XSLT action after removing from the top of the stack
@ -680,7 +693,13 @@ void ProcessorState::addLoadedDocument(Document* doc, String& url) {
Document* ProcessorState::getLoadedDocument(String& url) {
String docUrl;
URIUtils::getDocumentURI(url, docUrl);
return (Document*) loadedDocuments.get(docUrl);
if ((mMainStylesheetURL.length() > 0) && docUrl.isEqual(mMainStylesheetURL)) {
return xslDocument;
}
else if ((mMainSourceURL.length() > 0) && docUrl.isEqual(mMainSourceURL)) {
return mSourceDocument;
}
return (Document*)loadedDocuments.get(docUrl);
}
/**
@ -823,7 +842,7 @@ FunctionCall* ProcessorState::resolveFunctionCall(const String& name) {
String err;
if (DOCUMENT_FN.isEqual(name)) {
return new DocumentFunctionCall(this, xslDocument);
return new DocumentFunctionCall(this);
}
else if (KEY_FN.isEqual(name)) {
return new txKeyFunctionCall(this);
@ -868,20 +887,23 @@ FunctionCall* ProcessorState::resolveFunctionCall(const String& name) {
* Note: I will be moving this functionality elsewhere soon
**/
void ProcessorState::sortByDocumentOrder(NodeSet* nodes) {
if ((!nodes) || (nodes->size() < 2)) return;
if (!nodes || (nodes->size() < 2))
return;
NodeSet sorted(nodes->size());
sorted.setDuplicateChecking(MB_FALSE);
sorted.add(nodes->get(0));
int i = 1;
for ( ; i < nodes->size(); i++) {
int i, k;
for (i = 1; i < nodes->size(); i++) {
Node* node = nodes->get(i);
for (int k = i-1; k >= 0; k--) {
for (k = i - 1; k >= 0; k--) {
Node* tmpNode = sorted.get(k);
if (domHelper.appearsFirst(node, tmpNode) == tmpNode) {
if (k == i-1) sorted.add(node);
else sorted.add(k, node);
if (domHelper.appearsFirst(tmpNode, node) == tmpNode) {
if (k == i - 1)
sorted.add(node);
else
sorted.add(k, node);
break;
}
else if (k == 0) {
@ -969,8 +991,12 @@ void ProcessorState::initialize() {
//-- determine xsl properties
Element* element = NULL;
if (mSourceDocument) {
mMainSourceURL = mSourceDocument->getBaseURI();
}
if (xslDocument) {
element = xslDocument->getDocumentElement();
mMainStylesheetURL = xslDocument->getBaseURI();
}
if ( element ) {

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

@ -61,7 +61,7 @@ public:
* Creates a new ProcessorState for the given XSL document
* And result Document
**/
ProcessorState(Document& xslDocument, Document& resultDocument);
ProcessorState(Document& sourceDocument, Document& xslDocument, Document& resultDocument);
/**
* Destroys this ProcessorState
@ -196,6 +196,12 @@ public:
**/
MBool isXSLStripSpaceAllowed(Node* node);
/**
* Returns the current XSLT action from the top of the stack.
* @returns the XSLT action from the top of the stack
**/
Node* peekAction();
/**
* Adds the set of names to the Whitespace preserving element set
**/
@ -418,7 +424,10 @@ private:
XSLTAction* currentAction;
Stack nodeSetStack;
Document* mSourceDocument;
Document* xslDocument;
String mMainSourceURL;
String mMainStylesheetURL;
Document* resultDocument;
NamedMap exprHash;
NamedMap patternExprHash;

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

@ -60,7 +60,7 @@
#include "nsNetCID.h"
#include "nsIDOMClassInfo.h"
#include "nsIConsoleService.h"
//#include "nslog.h"
#include "nslog.h"
#else
#include "printers.h"
#include "TxLog.h"
@ -458,7 +458,7 @@ void XSLTProcessor::processTopLevel(Document* aSource,
String errMsg;
XMLParser xmlParser;
Document* xslDoc = xmlParser.getDocumentFromURI(href, element->getBaseURI(), errMsg);
Document* xslDoc = xmlParser.getDocumentFromURI(href, element->getBaseURI(), aStylesheet->getOwnerDocument(), errMsg);
if (!xslDoc) {
String err("error including XSL stylesheet: ");
@ -575,7 +575,7 @@ Document* XSLTProcessor::process
Document* result = new Document();
//-- create a new ProcessorState
ProcessorState ps(xslDocument, *result);
ProcessorState ps(xmlDocument, xslDocument, *result);
//-- add error observers
ListIterator* iter = errorObservers.iterator();
@ -618,7 +618,7 @@ void XSLTProcessor::process
Document* result = new Document();
//-- create a new ProcessorState
ProcessorState ps(xslDocument, *result);
ProcessorState ps(xmlDocument, xslDocument, *result);
//-- add error observers
ListIterator* iter = errorObservers.iterator();
@ -924,7 +924,6 @@ void XSLTProcessor::processAction
//-- xsl:apply-templates
case XSLType::APPLY_TEMPLATES :
{
String* mode = 0;
Attr* modeAttr = actionElement->getAttributeNode(MODE_ATTR);
if ( modeAttr ) mode = new String(modeAttr->getValue());
@ -1716,7 +1715,6 @@ void XSLTProcessor::processTemplateParams
else if (nodeType == Node::TEXT_NODE) {
if (!XMLUtils::isWhitespace(((Text*)tmpNode)->getData())) break;
}
else break;
tmpNode = tmpNode->getNextSibling();
}
}
@ -1863,8 +1861,8 @@ void XSLTProcessor::xslCopyOf(ExprResult* exprResult, ProcessorState* ps) {
} //-- xslCopyOf
#ifndef TX_EXE
//#define PRINTF NS_LOG_PRINTF(XSLT)
//#define FLUSH NS_LOG_FLUSH(XSLT)
#define PRINTF NS_LOG_PRINTF(XSLT)
#define FLUSH NS_LOG_FLUSH(XSLT)
NS_IMETHODIMP
XSLTProcessor::TransformDocument(nsIDOMNode* aSourceDOM,
nsIDOMNode* aStyleDOM,
@ -1909,7 +1907,7 @@ XSLTProcessor::TransformDocument(nsIDOMNode* aSourceDOM,
Document* resultDocument = new Document(aOutputDoc);
//-- create a new ProcessorState
ProcessorState* ps = new ProcessorState(*xslDocument, *resultDocument);
ProcessorState* ps = new ProcessorState(*sourceDocument, *xslDocument, *resultDocument);
//-- add error observers

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

@ -1,4 +1,5 @@
/*
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
@ -30,29 +31,26 @@
* in method DocumentFunctionCall::retrieveDocument
*/
/**
/*
* DocumentFunctionCall
* A representation of the XSLT additional function: document()
*/
#include "XSLTFunctions.h"
#include "XMLParser.h"
#include "XMLDOMUtils.h"
#include "URIUtils.h"
#include "Names.h"
/**
/*
* Creates a new DocumentFunctionCall.
**/
DocumentFunctionCall::DocumentFunctionCall(ProcessorState* ps, Document* xslDocument) : FunctionCall(DOCUMENT_FN)
*/
DocumentFunctionCall::DocumentFunctionCall(ProcessorState* aPs) : FunctionCall(DOCUMENT_FN)
{
this->processorState = ps;
this->xslDocument = xslDocument; //this is just untill we can get the actuall xsl tag
} //-- DocumentFunctionCall
mProcessorState = aPs;
}
/**
/*
* Evaluates this Expr based on the given context node and processor state
* NOTE: the implementation is incomplete since it does not make use of the
* second argument (base URI)
@ -60,12 +58,13 @@ DocumentFunctionCall::DocumentFunctionCall(ProcessorState* ps, Document* xslDocu
* @param ps the ContextState containing the stack information needed
* for evaluation
* @return the result of the evaluation
**/
ExprResult* DocumentFunctionCall::evaluate(Node* context, ContextState* cs) {
*/
ExprResult* DocumentFunctionCall::evaluate(Node* context, ContextState* cs)
{
NodeSet* nodeSet = new NodeSet();
//-- document( object, node-set? )
if ( requireParams(1, 2, cs) ) {
// document(object, node-set?)
if (requireParams(1, 2, cs)) {
ListIterator* iter = params.iterator();
Expr* param1 = (Expr*) iter->next();
ExprResult* exprResult1 = param1->evaluate(context, cs);
@ -73,11 +72,11 @@ ExprResult* DocumentFunctionCall::evaluate(Node* context, ContextState* cs) {
MBool baseURISet = MB_FALSE;
if (iter->hasNext()) {
// we have 2 arguments, get baseURI from the first node
// We have 2 arguments, get baseURI from the first node
// in the resulting nodeset
Expr* param2 = (Expr*) iter->next();
ExprResult* exprResult2 = param2->evaluate(context, cs);
if ( exprResult2->getResultType() != ExprResult::NODESET ) {
if (exprResult2->getResultType() != ExprResult::NODESET) {
String err("node-set expected as second argument to document(): ");
toString(err);
cs->recieveError(err);
@ -87,21 +86,22 @@ ExprResult* DocumentFunctionCall::evaluate(Node* context, ContextState* cs) {
// Make this true, even if nodeSet2 is empty. For relative URLs,
// we'll fail to load the document with an empty base URI, and for
// absolute URLs, the base URI doesn't matter.
// absolute URLs, the base URI doesn't matter
baseURISet = MB_TRUE;
NodeSet* nodeSet2 = (NodeSet*) exprResult2;
if (!nodeSet2->isEmpty()) {
processorState->sortByDocumentOrder(nodeSet2);
mProcessorState->sortByDocumentOrder(nodeSet2);
baseURI = nodeSet2->get(0)->getBaseURI();
}
delete exprResult2;
}
if ( exprResult1->getResultType() == ExprResult::NODESET ) {
if (exprResult1->getResultType() == ExprResult::NODESET) {
// The first argument is a NodeSet, iterate on its nodes
NodeSet* nodeSet1 = (NodeSet*) exprResult1;
for (int i=0; i<nodeSet1->size(); i++) {
int i;
for (i = 0; i < nodeSet1->size(); i++) {
Node* node = nodeSet1->get(i);
String uriStr;
XMLDOMUtils::getNodeValue(node, &uriStr);
@ -110,29 +110,29 @@ ExprResult* DocumentFunctionCall::evaluate(Node* context, ContextState* cs) {
// the baseUri of node itself
retrieveDocument(uriStr, node->getBaseURI(), *nodeSet, cs);
}
else
else {
retrieveDocument(uriStr, baseURI, *nodeSet, cs);
}
}
}
else {
// The first argument is not a NodeSet
String uriStr;
evaluateToString(param1, context, cs, uriStr);
if (!baseURISet) {
// XXX TODO: find the current xsl tag and get its base URI
// until then we use the xslDocument
retrieveDocument(uriStr, xslDocument->getBaseURI(), *nodeSet, cs);
Node* xsltElement = mProcessorState->peekAction();
retrieveDocument(uriStr, xsltElement->getBaseURI(), *nodeSet, cs);
}
else
else {
retrieveDocument(uriStr, baseURI, *nodeSet, cs);
}
}
delete exprResult1;
delete iter;
}
return nodeSet;
} //-- evaluate
}
/**
@ -145,20 +145,33 @@ ExprResult* DocumentFunctionCall::evaluate(Node* context, ContextState* cs) {
* @param resultNodeSet the NodeSet to append the document to
* @param cs the ContextState, used for reporting errors
*/
void DocumentFunctionCall::retrieveDocument(const String& uri, const String& baseUri, NodeSet& resultNodeSet, ContextState* cs)
void DocumentFunctionCall::retrieveDocument(const String& uri,
const String& baseUri,
NodeSet& resultNodeSet,
ContextState* cs)
{
String absUrl, frag;
Document* xmlDoc;
URIUtils::resolveHref(uri, baseUri, absUrl);
URIUtils::getFragmentIdentifier(absUrl, frag);
// try to get already loaded document
Document* xmlDoc = processorState->getLoadedDocument(absUrl);
if(!xmlDoc) {
xmlDoc = mProcessorState->getLoadedDocument(absUrl);
if (!xmlDoc) {
// open URI
String errMsg;
XMLParser xmlParser;
xmlDoc = xmlParser.getDocumentFromURI(uri, baseUri, errMsg);
Node* xsltElement;
xsltElement = mProcessorState->peekAction();
if (!xsltElement) {
// no xslt element
return;
}
xmlDoc = xmlParser.getDocumentFromURI(absUrl, "", xsltElement->getOwnerDocument(), errMsg);
if (!xmlDoc) {
String err("error in document() function: ");
err.append(errMsg);
@ -166,18 +179,17 @@ void DocumentFunctionCall::retrieveDocument(const String& uri, const String& bas
return;
}
// add to ProcessorState list of documents
processorState->addLoadedDocument(xmlDoc, absUrl);
mProcessorState->addLoadedDocument(xmlDoc, absUrl);
}
// append the to resultNodeSet
if(frag.length()) {
// append the document or the fragment to resultNodeSet
if (frag.length() > 0) {
Node* node = xmlDoc->getElementById(frag);
if(node)
if (node) {
resultNodeSet.add(node);
}
}
else
else {
resultNodeSet.add(xmlDoc);
}
}

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

@ -49,7 +49,7 @@ public:
/**
* Creates a new document() function call
**/
DocumentFunctionCall(ProcessorState* ps, Document* xslDocument);
DocumentFunctionCall(ProcessorState* aPs);
/**
* Evaluates this Expr based on the given context node and processor state
@ -63,8 +63,7 @@ public:
private:
void retrieveDocument(const String& uri,const String& baseUri, NodeSet &resultNodeSet, ContextState* cs);
Document* xslDocument;
ProcessorState* processorState;
ProcessorState* mProcessorState;
};
/*