486 lines
12 KiB
C++
486 lines
12 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public License
|
|
* Version 1.0 (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 Netscape are Copyright (C) 1998
|
|
* Netscape Communications Corporation. All Rights Reserved.
|
|
*/
|
|
|
|
|
|
#include "nsXMLDocument.h"
|
|
#include "nsWellFormedDTD.h"
|
|
#include "nsParserCIID.h"
|
|
#include "nsIParser.h"
|
|
#include "nsIXMLContent.h"
|
|
#include "nsIXMLContentSink.h"
|
|
#include "nsIPresShell.h"
|
|
#include "nsIPresContext.h"
|
|
#include "nsIContentViewerContainer.h"
|
|
#include "nsIWebShell.h"
|
|
#include "nsIDocumentLoader.h"
|
|
#include "nsIHTMLContent.h"
|
|
#include "nsHTMLParts.h"
|
|
#include "nsIHTMLStyleSheet.h"
|
|
#include "nsIHTMLCSSStyleSheet.h"
|
|
#include "nsIStyleSet.h"
|
|
#include "nsRepository.h"
|
|
#include "nsIDOMComment.h"
|
|
#include "nsIDOMElement.h"
|
|
#include "nsIDOMText.h"
|
|
|
|
// XXX The XML world depends on the html atoms
|
|
#include "nsHTMLAtoms.h"
|
|
|
|
static NS_DEFINE_IID(kIDOMDocumentIID, NS_IDOMDOCUMENT_IID);
|
|
static NS_DEFINE_IID(kIDocumentIID, NS_IDOCUMENT_IID);
|
|
static NS_DEFINE_IID(kIXMLDocumentIID, NS_IXMLDOCUMENT_IID);
|
|
static NS_DEFINE_IID(kIWebShellIID, NS_IWEB_SHELL_IID);
|
|
static NS_DEFINE_IID(kIDOMCommentIID, NS_IDOMCOMMENT_IID);
|
|
static NS_DEFINE_IID(kIDOMElementIID, NS_IDOMELEMENT_IID);
|
|
static NS_DEFINE_IID(kIDOMTextIID, NS_IDOMTEXT_IID);
|
|
static NS_DEFINE_IID(kIHTMLContentContainerIID, NS_IHTMLCONTENTCONTAINER_IID);
|
|
|
|
|
|
NS_LAYOUT nsresult
|
|
NS_NewXMLDocument(nsIDocument** aInstancePtrResult)
|
|
{
|
|
nsXMLDocument* doc = new nsXMLDocument();
|
|
return doc->QueryInterface(kIDocumentIID, (void**) aInstancePtrResult);
|
|
}
|
|
|
|
nsXMLDocument::nsXMLDocument()
|
|
{
|
|
mParser = nsnull;
|
|
mNameSpaces = nsnull;
|
|
mAttrStyleSheet = nsnull;
|
|
mInlineStyleSheet = nsnull;
|
|
mProlog = nsnull;
|
|
mEpilog = nsnull;
|
|
|
|
// XXX The XML world depends on the html atoms
|
|
nsHTMLAtoms::AddrefAtoms();
|
|
}
|
|
|
|
nsXMLDocument::~nsXMLDocument()
|
|
{
|
|
NS_IF_RELEASE(mParser);
|
|
if (nsnull != mNameSpaces) {
|
|
int i;
|
|
for (i = 0; i < mNameSpaces->Count(); i++) {
|
|
nsXMLNameSpace *ns = (nsXMLNameSpace *)mNameSpaces->ElementAt(i);
|
|
|
|
if (nsnull != ns) {
|
|
NS_IF_RELEASE(ns->mPrefix);
|
|
delete ns->mURI;
|
|
delete ns;
|
|
}
|
|
}
|
|
mNameSpaces = nsnull;
|
|
}
|
|
if (nsnull != mAttrStyleSheet) {
|
|
mAttrStyleSheet->SetOwningDocument(nsnull);
|
|
NS_RELEASE(mAttrStyleSheet);
|
|
}
|
|
if (nsnull != mInlineStyleSheet) {
|
|
mInlineStyleSheet->SetOwningDocument(nsnull);
|
|
NS_RELEASE(mInlineStyleSheet);
|
|
}
|
|
if (nsnull != mProlog) {
|
|
delete mProlog;
|
|
}
|
|
if (nsnull != mEpilog) {
|
|
delete mProlog;
|
|
}
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXMLDocument::QueryInterface(REFNSIID aIID,
|
|
void** aInstancePtr)
|
|
{
|
|
if (NULL == aInstancePtr) {
|
|
return NS_ERROR_NULL_POINTER;
|
|
}
|
|
if (aIID.Equals(kIXMLDocumentIID)) {
|
|
NS_ADDREF_THIS();
|
|
*aInstancePtr = (void**) (nsIXMLDocument *)this;
|
|
return NS_OK;
|
|
}
|
|
if (aIID.Equals(kIHTMLContentContainerIID)) {
|
|
NS_ADDREF_THIS();
|
|
*aInstancePtr = (void**) (nsIHTMLContentContainer *)this;
|
|
return NS_OK;
|
|
}
|
|
return nsDocument::QueryInterface(aIID, aInstancePtr);
|
|
}
|
|
|
|
nsrefcnt nsXMLDocument::AddRef()
|
|
{
|
|
return nsDocument::AddRef();
|
|
}
|
|
|
|
nsrefcnt nsXMLDocument::Release()
|
|
{
|
|
return nsDocument::Release();
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXMLDocument::StartDocumentLoad(nsIURL *aUrl,
|
|
nsIContentViewerContainer* aContainer,
|
|
nsIStreamListener **aDocListener,
|
|
const char* aCommand)
|
|
{
|
|
nsresult rv = nsDocument::StartDocumentLoad(aUrl, aContainer,
|
|
aDocListener);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
if (nsnull != mAttrStyleSheet) {
|
|
mAttrStyleSheet->SetOwningDocument(nsnull);
|
|
NS_RELEASE(mAttrStyleSheet);
|
|
}
|
|
if (nsnull != mInlineStyleSheet) {
|
|
mInlineStyleSheet->SetOwningDocument(nsnull);
|
|
NS_RELEASE(mInlineStyleSheet);
|
|
}
|
|
|
|
nsIWebShell* webShell;
|
|
|
|
static NS_DEFINE_IID(kCParserIID, NS_IPARSER_IID);
|
|
static NS_DEFINE_IID(kCParserCID, NS_PARSER_IID);
|
|
|
|
rv = nsRepository::CreateInstance(kCParserCID,
|
|
nsnull,
|
|
kCParserIID,
|
|
(void **)&mParser);
|
|
if (NS_OK == rv) {
|
|
nsIXMLContentSink* sink;
|
|
|
|
aContainer->QueryInterface(kIWebShellIID, (void**)&webShell);
|
|
rv = NS_NewXMLContentSink(&sink, this, aUrl, webShell);
|
|
NS_IF_RELEASE(webShell);
|
|
|
|
if (NS_OK == rv) {
|
|
// For the HTML content within a document
|
|
if (NS_OK == NS_NewHTMLStyleSheet(&mAttrStyleSheet, aUrl, this)) {
|
|
AddStyleSheet(mAttrStyleSheet); // tell the world about our new style sheet
|
|
}
|
|
if (NS_OK == NS_NewHTMLCSSStyleSheet(&mInlineStyleSheet, aUrl, this)) {
|
|
AddStyleSheet(mInlineStyleSheet); // tell the world about our new style sheet
|
|
}
|
|
|
|
// Set the parser as the stream listener for the document loader...
|
|
static NS_DEFINE_IID(kIStreamListenerIID, NS_ISTREAMLISTENER_IID);
|
|
rv = mParser->QueryInterface(kIStreamListenerIID, (void**)aDocListener);
|
|
|
|
if (NS_OK == rv) {
|
|
|
|
nsIDTD* theDTD=0;
|
|
// XXX For now, we'll use the HTML DTD
|
|
NS_NewWellFormed_DTD(&theDTD);
|
|
mParser->RegisterDTD(theDTD);
|
|
mParser->SetCommand(aCommand);
|
|
mParser->SetContentSink(sink);
|
|
mParser->Parse(aUrl);
|
|
}
|
|
NS_RELEASE(sink);
|
|
}
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXMLDocument::EndLoad()
|
|
{
|
|
NS_IF_RELEASE(mParser);
|
|
return nsDocument::EndLoad();
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXMLDocument::GetAttributeStyleSheet(nsIHTMLStyleSheet** aResult)
|
|
{
|
|
NS_PRECONDITION(nsnull != aResult, "null ptr");
|
|
if (nsnull == aResult) {
|
|
return NS_ERROR_NULL_POINTER;
|
|
}
|
|
*aResult = mAttrStyleSheet;
|
|
if (nsnull == mAttrStyleSheet) {
|
|
return NS_ERROR_NOT_AVAILABLE; // probably not the right error...
|
|
}
|
|
else {
|
|
NS_ADDREF(mAttrStyleSheet);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXMLDocument::GetInlineStyleSheet(nsIHTMLCSSStyleSheet** aResult)
|
|
{
|
|
NS_PRECONDITION(nsnull != aResult, "null ptr");
|
|
if (nsnull == aResult) {
|
|
return NS_ERROR_NULL_POINTER;
|
|
}
|
|
*aResult = mInlineStyleSheet;
|
|
if (nsnull == mInlineStyleSheet) {
|
|
return NS_ERROR_NOT_AVAILABLE; // probably not the right error...
|
|
}
|
|
else {
|
|
NS_ADDREF(mInlineStyleSheet);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
void nsXMLDocument::AddStyleSheetToSet(nsIStyleSheet* aSheet, nsIStyleSet* aSet)
|
|
{
|
|
if ((nsnull != mInlineStyleSheet) && (aSheet != mInlineStyleSheet)) {
|
|
aSet->InsertDocStyleSheetAfter(aSheet, mInlineStyleSheet);
|
|
}
|
|
else {
|
|
aSet->InsertDocStyleSheetBefore(aSheet, nsnull); // put it in front
|
|
}
|
|
}
|
|
|
|
// nsIDOMDocument interface
|
|
NS_IMETHODIMP
|
|
nsXMLDocument::GetDoctype(nsIDOMDocumentType** aDocumentType)
|
|
{
|
|
// XXX TBI
|
|
*aDocumentType = nsnull;
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXMLDocument::CreateCDATASection(const nsString& aData, nsIDOMCDATASection** aReturn)
|
|
{
|
|
// XXX TBI
|
|
*aReturn = nsnull;
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXMLDocument::CreateEntityReference(const nsString& aName, nsIDOMEntityReference** aReturn)
|
|
{
|
|
// XXX TBI
|
|
*aReturn = nsnull;
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXMLDocument::CreateComment(const nsString& aData, nsIDOMComment** aReturn)
|
|
{
|
|
// XXX Should just be regular nsIContent
|
|
nsIHTMLContent* comment = nsnull;
|
|
nsresult rv = NS_NewCommentNode(&comment);
|
|
|
|
if (NS_OK == rv) {
|
|
rv = comment->QueryInterface(kIDOMCommentIID, (void**)aReturn);
|
|
(*aReturn)->AppendData(aData);
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXMLDocument::CreateProcessingInstruction(const nsString& aTarget, const nsString& aData, nsIDOMProcessingInstruction** aReturn)
|
|
{
|
|
// XXX TBI
|
|
*aReturn = nsnull;
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXMLDocument::CreateAttribute(const nsString& aName, nsIDOMAttr** aReturn)
|
|
{
|
|
// XXX TBI
|
|
*aReturn = nsnull;
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXMLDocument::CreateElement(const nsString& aTagName,
|
|
nsIDOMElement** aReturn)
|
|
{
|
|
// XXX Should actually check parse namespace, determine
|
|
// current namespace scope and, potentially, create new
|
|
// HTML content form tags with a HTML prefix.
|
|
nsIXMLContent* content;
|
|
nsIAtom* tag = NS_NewAtom(aTagName);
|
|
nsresult rv = NS_NewXMLElement(&content, tag);
|
|
NS_RELEASE(tag);
|
|
|
|
if (NS_OK != rv) {
|
|
return rv;
|
|
}
|
|
rv = content->QueryInterface(kIDOMElementIID, (void**)aReturn);
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXMLDocument::CreateTextNode(const nsString& aData, nsIDOMText** aReturn)
|
|
{
|
|
// XXX Should just be regular nsIContent
|
|
nsIHTMLContent* text = nsnull;
|
|
nsresult rv = NS_NewTextNode(&text);
|
|
|
|
if (NS_OK == rv) {
|
|
rv = text->QueryInterface(kIDOMTextIID, (void**)aReturn);
|
|
(*aReturn)->AppendData(aData);
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
|
|
// nsIXMLDocument interface
|
|
NS_IMETHODIMP
|
|
nsXMLDocument::RegisterNameSpace(nsIAtom *aPrefix, const nsString& aURI,
|
|
PRInt32& aNameSpaceId)
|
|
{
|
|
if (nsnull == mNameSpaces) {
|
|
mNameSpaces = new nsVoidArray();
|
|
if (nsnull == mNameSpaces) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
|
|
nsXMLNameSpace* ns = new nsXMLNameSpace;
|
|
if (nsnull == ns) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
ns->mPrefix = aPrefix;
|
|
NS_IF_ADDREF(ns->mPrefix);
|
|
ns->mURI = new nsString(aURI);
|
|
|
|
mNameSpaces->AppendElement((void *)ns);
|
|
aNameSpaceId = mNameSpaces->Count();
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXMLDocument::GetNameSpaceURI(PRInt32 aNameSpaceId, nsString& aURI)
|
|
{
|
|
if (nsnull == mNameSpaces) {
|
|
return NS_ERROR_ILLEGAL_VALUE;
|
|
}
|
|
|
|
nsXMLNameSpace *ns = (nsXMLNameSpace *)mNameSpaces->ElementAt(aNameSpaceId - 1);
|
|
if (nsnull == ns) {
|
|
return NS_ERROR_ILLEGAL_VALUE;
|
|
}
|
|
aURI.SetString(*ns->mURI);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXMLDocument::GetNameSpacePrefix(PRInt32 aNameSpaceId, nsIAtom*& aPrefix)
|
|
{
|
|
if (nsnull == mNameSpaces) {
|
|
return NS_ERROR_ILLEGAL_VALUE;
|
|
}
|
|
|
|
nsXMLNameSpace *ns = (nsXMLNameSpace *)mNameSpaces->ElementAt(aNameSpaceId - 1);
|
|
if (nsnull == ns) {
|
|
return NS_ERROR_ILLEGAL_VALUE;
|
|
}
|
|
|
|
aPrefix = ns->mPrefix;
|
|
NS_IF_ADDREF(aPrefix);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXMLDocument::PrologElementAt(PRInt32 aIndex, nsIContent** aContent)
|
|
{
|
|
if (nsnull == mProlog) {
|
|
*aContent = nsnull;
|
|
}
|
|
else {
|
|
*aContent = (nsIContent *)mProlog->ElementAt(aIndex);
|
|
NS_ADDREF(*aContent);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXMLDocument::PrologCount(PRInt32* aCount)
|
|
{
|
|
if (nsnull == mProlog) {
|
|
*aCount = 0;
|
|
}
|
|
else {
|
|
*aCount = mProlog->Count();
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXMLDocument::AppendToProlog(nsIContent* aContent)
|
|
{
|
|
if (nsnull == mProlog) {
|
|
mProlog = new nsVoidArray();
|
|
}
|
|
|
|
mProlog->AppendElement((void *)aContent);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXMLDocument::EpilogElementAt(PRInt32 aIndex, nsIContent** aContent)
|
|
{
|
|
if (nsnull == mEpilog) {
|
|
*aContent = nsnull;
|
|
}
|
|
else {
|
|
*aContent = (nsIContent *)mEpilog->ElementAt(aIndex);
|
|
NS_ADDREF(*aContent);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXMLDocument::EpilogCount(PRInt32* aCount)
|
|
{
|
|
if (nsnull == mEpilog) {
|
|
*aCount = 0;
|
|
}
|
|
else {
|
|
*aCount = mEpilog->Count();
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXMLDocument::AppendToEpilog(nsIContent* aContent)
|
|
{
|
|
if (nsnull == mEpilog) {
|
|
mEpilog = new nsVoidArray();
|
|
}
|
|
|
|
mEpilog->AppendElement((void *)aContent);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
|