Bug 221335: Speed up output by using internal methods and interfaces rather than nsIDOMNode and friends. r/sr=peterv

This commit is contained in:
cvshook%sicking.cc 2006-10-03 02:22:22 +00:00
parent 068b646342
commit 38126837d0
23 changed files with 934 additions and 674 deletions

View File

@ -3188,6 +3188,10 @@ PRBool
nsContentUtils::IsValidNodeName(nsIAtom *aLocalName, nsIAtom *aPrefix,
PRInt32 aNamespaceID)
{
if (aNamespaceID == kNameSpaceID_Unknown) {
return PR_FALSE;
}
if (!aPrefix) {
// If the prefix is null, then either the QName must be xmlns or the
// namespace must not be XMLNS.

View File

@ -804,6 +804,7 @@ GK_ATOM(topmargin, "topmargin")
GK_ATOM(toppadding, "toppadding")
GK_ATOM(tr, "tr")
GK_ATOM(transform, "transform")
GK_ATOM(transformiix, "transformiix")
GK_ATOM(translate, "translate")
GK_ATOM(transparent, "transparent")
GK_ATOM(tree, "tree")

View File

@ -346,33 +346,36 @@ nsXMLContentSink::DidBuildModel()
}
NS_IMETHODIMP
nsXMLContentSink::OnDocumentCreated(nsIDOMDocument* aResultDocument)
nsXMLContentSink::OnDocumentCreated(nsIDocument* aResultDocument)
{
NS_ENSURE_ARG(aResultDocument);
nsCOMPtr<nsIContentViewer> contentViewer;
mDocShell->GetContentViewer(getter_AddRefs(contentViewer));
if (contentViewer) {
return contentViewer->SetDOMDocument(aResultDocument);
nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(aResultDocument);
return contentViewer->SetDOMDocument(doc);
}
return NS_OK;
}
NS_IMETHODIMP
nsXMLContentSink::OnTransformDone(nsresult aResult,
nsIDOMDocument* aResultDocument)
nsIDocument* aResultDocument)
{
NS_ASSERTION(NS_FAILED(aResult) || aResultDocument,
"Don't notify about transform success without a document.");
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(aResultDocument);
nsCOMPtr<nsIContentViewer> contentViewer;
mDocShell->GetContentViewer(getter_AddRefs(contentViewer));
if (NS_FAILED(aResult) && contentViewer) {
// Transform failed.
if (aResultDocument) {
if (domDoc) {
// We have an error document.
contentViewer->SetDOMDocument(aResultDocument);
contentViewer->SetDOMDocument(domDoc);
}
else {
// We don't have an error document, display the
@ -386,7 +389,7 @@ nsXMLContentSink::OnTransformDone(nsresult aResult,
if (NS_SUCCEEDED(aResult) || aResultDocument) {
// Transform succeeded or it failed and we have an error
// document to display.
mDocument = do_QueryInterface(aResultDocument);
mDocument = aResultDocument;
}
nsIScriptLoader *loader = originalDocument->GetScriptLoader();

View File

@ -89,8 +89,8 @@ public:
virtual nsISupports *GetTarget();
// nsITransformObserver
NS_IMETHOD OnDocumentCreated(nsIDOMDocument *aResultDocument);
NS_IMETHOD OnTransformDone(nsresult aResult, nsIDOMDocument *aResultDocument);
NS_IMETHOD OnDocumentCreated(nsIDocument *aResultDocument);
NS_IMETHOD OnTransformDone(nsresult aResult, nsIDocument *aResultDocument);
static void ParsePIData(const nsString &aData, nsString &aHref,
nsString &aTitle, nsString &aMedia,

View File

@ -48,8 +48,8 @@ class nsIPrincipal;
class nsString;
#define NS_ITRANSFORMOBSERVER_IID \
{0xcce88481, 0x6eb3, 0x11d6, \
{ 0xa7, 0xf2, 0x8d, 0x82, 0xcd, 0x2a, 0xf3, 0x7c }}
{ 0x04b2d17c, 0xe98d, 0x45f5, \
{ 0x9a, 0x67, 0xb7, 0x01, 0x19, 0x59, 0x7d, 0xe7 } }
class nsITransformObserver : public nsISupports
{
@ -57,10 +57,10 @@ public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ITRANSFORMOBSERVER_IID)
NS_IMETHOD OnDocumentCreated(nsIDOMDocument *aResultDocument) = 0;
NS_IMETHOD OnDocumentCreated(nsIDocument *aResultDocument) = 0;
NS_IMETHOD OnTransformDone(nsresult aResult,
nsIDOMDocument *aResultDocument) = 0;
nsIDocument *aResultDocument) = 0;
};

View File

@ -138,4 +138,7 @@
#define NS_ERROR_XPATH_UNBALANCED_CURLY_BRACE \
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XSLT, 29)
#define NS_ERROR_XSLT_BAD_NODE_NAME \
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XSLT, 30)
#endif // __TX_ERROR

View File

@ -79,4 +79,13 @@ void TX_ToLowerCase(const nsAString& aSource, nsAString& aDest);
#endif
inline already_AddRefed<nsIAtom>
TX_ToLowerCaseAtom(nsIAtom* aAtom)
{
nsAutoString str;
aAtom->ToString(str);
TX_ToLowerCase(str);
return do_GetAtom(str);
}
#endif // txStringUtils_h__

View File

@ -407,6 +407,22 @@ txXPathNodeUtils::getLocalName(const txXPathNode& aNode)
return localName;
}
nsIAtom*
txXPathNodeUtils::getPrefix(const txXPathNode& aNode)
{
if (aNode.isDocument()) {
return nsnull;
}
if (aNode.isContent()) {
// All other nsIContent node types but elements have a null prefix
// which is what we want here.
return aNode.Content()->NodeInfo()->GetPrefixAtom();
}
return aNode.Content()->GetAttrNameAt(aNode.mIndex)->GetPrefix();
}
/* static */
void
txXPathNodeUtils::getLocalName(const txXPathNode& aNode, nsAString& aLocalName)

View File

@ -116,6 +116,7 @@ public:
static PRBool getAttr(const txXPathNode& aNode, nsIAtom* aLocalName,
PRInt32 aNSID, nsAString& aValue);
static already_AddRefed<nsIAtom> getLocalName(const txXPathNode& aNode);
static nsIAtom* getPrefix(const txXPathNode& aNode);
static void getLocalName(const txXPathNode& aNode, nsAString& aLocalName);
static void getNodeName(const txXPathNode& aNode,
nsAString& aName);

View File

@ -44,6 +44,7 @@ class txOutputTransaction
public:
enum txTransactionType {
eAttributeTransaction,
eAttributeAtomTransaction,
eCharacterTransaction,
eCharacterNoOETransaction,
eCommentTransaction,
@ -51,6 +52,7 @@ public:
eEndElementTransaction,
ePITransaction,
eStartDocumentTransaction,
eStartElementAtomTransaction,
eStartElementTransaction
};
txOutputTransaction(txTransactionType aType)
@ -98,32 +100,76 @@ public:
nsString mData;
};
class txElementTransaction : public txOutputTransaction
class txStartElementAtomTransaction : public txOutputTransaction
{
public:
txElementTransaction(txTransactionType aType, const nsAString& aName,
PRInt32 aNsID)
: txOutputTransaction(aType),
mName(aName),
txStartElementAtomTransaction(nsIAtom* aPrefix, nsIAtom* aLocalName,
nsIAtom* aLowercaseLocalName, PRInt32 aNsID)
: txOutputTransaction(eStartElementAtomTransaction),
mPrefix(aPrefix),
mLocalName(aLocalName),
mLowercaseLocalName(aLowercaseLocalName),
mNsID(aNsID)
{
}
nsString mName;
nsCOMPtr<nsIAtom> mPrefix;
nsCOMPtr<nsIAtom> mLocalName;
nsCOMPtr<nsIAtom> mLowercaseLocalName;
PRInt32 mNsID;
};
class txStartElementTransaction : public txOutputTransaction
{
public:
txStartElementTransaction(nsIAtom* aPrefix,
const nsSubstring& aLocalName, PRInt32 aNsID)
: txOutputTransaction(eStartElementTransaction),
mPrefix(aPrefix),
mLocalName(aLocalName),
mNsID(aNsID)
{
}
nsCOMPtr<nsIAtom> mPrefix;
nsString mLocalName;
PRInt32 mNsID;
};
class txAttributeTransaction : public txOutputTransaction
{
public:
txAttributeTransaction(const nsAString& aName, PRInt32 aNsID,
const nsAString& aValue)
txAttributeTransaction(nsIAtom* aPrefix,
const nsSubstring& aLocalName, PRInt32 aNsID,
const nsString& aValue)
: txOutputTransaction(eAttributeTransaction),
mName(aName),
mPrefix(aPrefix),
mLocalName(aLocalName),
mNsID(aNsID),
mValue(aValue)
{
}
nsString mName;
nsCOMPtr<nsIAtom> mPrefix;
nsString mLocalName;
PRInt32 mNsID;
nsString mValue;
};
class txAttributeAtomTransaction : public txOutputTransaction
{
public:
txAttributeAtomTransaction(nsIAtom* aPrefix, nsIAtom* aLocalName,
nsIAtom* aLowercaseLocalName,
PRInt32 aNsID, const nsString& aValue)
: txOutputTransaction(eAttributeAtomTransaction),
mPrefix(aPrefix),
mLocalName(aLocalName),
mLowercaseLocalName(aLowercaseLocalName),
mNsID(aNsID),
mValue(aValue)
{
}
nsCOMPtr<nsIAtom> mPrefix;
nsCOMPtr<nsIAtom> mLocalName;
nsCOMPtr<nsIAtom> mLowercaseLocalName;
PRInt32 mNsID;
nsString mValue;
};
@ -138,8 +184,9 @@ txBufferingHandler::~txBufferingHandler()
}
nsresult
txBufferingHandler::attribute(const nsAString& aName, const PRInt32 aNsID,
const nsAString& aValue)
txBufferingHandler::attribute(nsIAtom* aPrefix, nsIAtom* aLocalName,
nsIAtom* aLowercaseLocalName, PRInt32 aNsID,
const nsString& aValue)
{
NS_ENSURE_TRUE(mBuffer, NS_ERROR_OUT_OF_MEMORY);
@ -149,14 +196,34 @@ txBufferingHandler::attribute(const nsAString& aName, const PRInt32 aNsID,
}
txOutputTransaction* transaction =
new txAttributeTransaction(aName, aNsID, aValue);
new txAttributeAtomTransaction(aPrefix, aLocalName,
aLowercaseLocalName, aNsID,
aValue);
NS_ENSURE_TRUE(transaction, NS_ERROR_OUT_OF_MEMORY);
return mBuffer->addTransaction(transaction);
}
nsresult
txBufferingHandler::characters(const nsAString& aData, PRBool aDOE)
txBufferingHandler::attribute(nsIAtom* aPrefix, const nsSubstring& aLocalName,
const PRInt32 aNsID, const nsString& aValue)
{
NS_ENSURE_TRUE(mBuffer, NS_ERROR_OUT_OF_MEMORY);
if (!mCanAddAttribute) {
// XXX ErrorReport: Can't add attributes without element
return NS_OK;
}
txOutputTransaction* transaction =
new txAttributeTransaction(aPrefix, aLocalName, aNsID, aValue);
NS_ENSURE_TRUE(transaction, NS_ERROR_OUT_OF_MEMORY);
return mBuffer->addTransaction(transaction);
}
nsresult
txBufferingHandler::characters(const nsSubstring& aData, PRBool aDOE)
{
NS_ENSURE_TRUE(mBuffer, NS_ERROR_OUT_OF_MEMORY);
@ -182,7 +249,7 @@ txBufferingHandler::characters(const nsAString& aData, PRBool aDOE)
}
nsresult
txBufferingHandler::comment(const nsAString& aData)
txBufferingHandler::comment(const nsString& aData)
{
NS_ENSURE_TRUE(mBuffer, NS_ERROR_OUT_OF_MEMORY);
@ -207,23 +274,22 @@ txBufferingHandler::endDocument(nsresult aResult)
}
nsresult
txBufferingHandler::endElement(const nsAString& aName, const PRInt32 aNsID)
txBufferingHandler::endElement()
{
NS_ENSURE_TRUE(mBuffer, NS_ERROR_OUT_OF_MEMORY);
mCanAddAttribute = PR_FALSE;
txOutputTransaction* transaction =
new txElementTransaction(txOutputTransaction::eEndElementTransaction,
aName, aNsID);
new txOutputTransaction(txOutputTransaction::eEndElementTransaction);
NS_ENSURE_TRUE(transaction, NS_ERROR_OUT_OF_MEMORY);
return mBuffer->addTransaction(transaction);
}
nsresult
txBufferingHandler::processingInstruction(const nsAString& aTarget,
const nsAString& aData)
txBufferingHandler::processingInstruction(const nsString& aTarget,
const nsString& aData)
{
NS_ENSURE_TRUE(mBuffer, NS_ERROR_OUT_OF_MEMORY);
@ -249,15 +315,33 @@ txBufferingHandler::startDocument()
}
nsresult
txBufferingHandler::startElement(const nsAString& aName, const PRInt32 aNsID)
txBufferingHandler::startElement(nsIAtom* aPrefix, nsIAtom* aLocalName,
nsIAtom* aLowercaseLocalName,
PRInt32 aNsID)
{
NS_ENSURE_TRUE(mBuffer, NS_ERROR_OUT_OF_MEMORY);
mCanAddAttribute = PR_TRUE;
txOutputTransaction* transaction =
new txElementTransaction(txOutputTransaction::eStartElementTransaction,
aName, aNsID);
new txStartElementAtomTransaction(aPrefix, aLocalName,
aLowercaseLocalName, aNsID);
NS_ENSURE_TRUE(transaction, NS_ERROR_OUT_OF_MEMORY);
return mBuffer->addTransaction(transaction);
}
nsresult
txBufferingHandler::startElement(nsIAtom* aPrefix,
const nsSubstring& aLocalName,
const PRInt32 aNsID)
{
NS_ENSURE_TRUE(mBuffer, NS_ERROR_OUT_OF_MEMORY);
mCanAddAttribute = PR_TRUE;
txOutputTransaction* transaction =
new txStartElementTransaction(aPrefix, aLocalName, aNsID);
NS_ENSURE_TRUE(transaction, NS_ERROR_OUT_OF_MEMORY);
return mBuffer->addTransaction(transaction);
@ -301,11 +385,23 @@ flushTransaction(void* aElement, void *aData)
nsresult rv;
switch (transaction->mType) {
case txOutputTransaction::eAttributeAtomTransaction:
{
txAttributeAtomTransaction* transaction =
NS_STATIC_CAST(txAttributeAtomTransaction*, aElement);
rv = handler->attribute(transaction->mPrefix,
transaction->mLocalName,
transaction->mLowercaseLocalName,
transaction->mNsID,
transaction->mValue);
break;
}
case txOutputTransaction::eAttributeTransaction:
{
txAttributeTransaction* attrTransaction =
NS_STATIC_CAST(txAttributeTransaction*, aElement);
rv = handler->attribute(attrTransaction->mName,
rv = handler->attribute(attrTransaction->mPrefix,
attrTransaction->mLocalName,
attrTransaction->mNsID,
attrTransaction->mValue);
break;
@ -334,10 +430,7 @@ flushTransaction(void* aElement, void *aData)
}
case txOutputTransaction::eEndElementTransaction:
{
txElementTransaction* elementTransaction =
NS_STATIC_CAST(txElementTransaction*, aElement);
rv = handler->endElement(elementTransaction->mName,
elementTransaction->mNsID);
rv = handler->endElement();
break;
}
case txOutputTransaction::ePITransaction:
@ -353,12 +446,23 @@ flushTransaction(void* aElement, void *aData)
rv = handler->startDocument();
break;
}
case txOutputTransaction::eStartElementAtomTransaction:
{
txStartElementAtomTransaction* transaction =
NS_STATIC_CAST(txStartElementAtomTransaction*, aElement);
rv = handler->startElement(transaction->mPrefix,
transaction->mLocalName,
transaction->mLowercaseLocalName,
transaction->mNsID);
break;
}
case txOutputTransaction::eStartElementTransaction:
{
txElementTransaction* elementTransaction =
NS_STATIC_CAST(txElementTransaction*, aElement);
rv = handler->startElement(elementTransaction->mName,
elementTransaction->mNsID);
txStartElementTransaction* transaction =
NS_STATIC_CAST(txStartElementTransaction*, aElement);
rv = handler->startElement(transaction->mPrefix,
transaction->mLocalName,
transaction->mNsID);
break;
}
}

View File

@ -365,34 +365,22 @@ txExecutionState::popEvalContext()
}
nsresult
txExecutionState::pushString(const nsAString& aStr)
txExecutionState::pushBool(PRBool aBool)
{
if (!mStringStack.AppendString(aStr)) {
return NS_ERROR_OUT_OF_MEMORY;
}
return NS_OK;
return mBoolStack.AppendElement(aBool) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}
void
txExecutionState::popString(nsAString& aStr)
PRBool
txExecutionState::popBool()
{
PRInt32 count = mStringStack.Count() - 1;
NS_ASSERTION(count >= 0, "stack is empty");
mStringStack.StringAt(count, aStr);
mStringStack.RemoveStringAt(count);
}
NS_ASSERTION(mBoolStack.Length(), "popping from empty stack");
PRUint32 last = mBoolStack.Length() - 1;
NS_ENSURE_TRUE(last != (PRUint32)-1, PR_FALSE);
nsresult
txExecutionState::pushInt(PRInt32 aInt)
{
return mIntStack.push(NS_INT32_TO_PTR(aInt));
}
PRBool res = mBoolStack.ElementAt(last);
mBoolStack.RemoveElementAt(last);
PRInt32
txExecutionState::popInt()
{
return NS_PTR_TO_INT32(mIntStack.pop());
return res;
}
nsresult

View File

@ -50,6 +50,7 @@
#include "txKey.h"
#include "txStylesheet.h"
#include "txXPathTreeWalker.h"
#include "nsTArray.h"
class txAOutputHandlerFactory;
class txAXMLEventHandler;
@ -113,10 +114,8 @@ public:
// Stack functions
nsresult pushEvalContext(txIEvalContext* aContext);
txIEvalContext* popEvalContext();
nsresult pushString(const nsAString& aStr);
void popString(nsAString& aStr);
nsresult pushInt(PRInt32 aInt);
PRInt32 popInt();
nsresult pushBool(PRBool aBool);
PRBool popBool();
nsresult pushResultHandler(txAXMLEventHandler* aHandler);
txAXMLEventHandler* popResultHandler();
nsresult pushTemplateRule(txStylesheet::ImportFrame* aFrame,
@ -159,10 +158,9 @@ private:
txStack mReturnStack;
txStack mLocalVarsStack;
txStack mEvalContextStack;
txStack mIntStack;
nsTArray<PRPackedBool> mBoolStack;
txStack mResultHandlerStack;
txStack mParamStack;
nsStringArray mStringStack;
txInstruction* mNextInstruction;
txVariableMap* mLocalVariables;
txVariableMap mGlobalVariableValues;

View File

@ -140,51 +140,39 @@ txAttribute::execute(txExecutionState& aEs)
const PRUnichar* colon;
if (!XMLUtils::isValidQName(name, &colon) ||
TX_StringEqualsAtom(name, txXMLAtoms::xmlns)) {
// truncate name to indicate failure
name.Truncate();
return NS_OK;
}
nsCOMPtr<nsIAtom> prefix;
PRUint32 lnameStart = 0;
if (colon) {
prefix = do_GetAtom(Substring(name.get(), colon));
lnameStart = colon - name.get() + 1;
}
PRInt32 nsId = kNameSpaceID_None;
if (!name.IsEmpty()) {
if (mNamespace) {
nsAutoString nspace;
rv = mNamespace->evaluateToString(aEs.getEvalContext(),
nspace);
NS_ENSURE_SUCCESS(rv, rv);
if (mNamespace) {
nsAutoString nspace;
rv = mNamespace->evaluateToString(aEs.getEvalContext(),
nspace);
NS_ENSURE_SUCCESS(rv, rv);
if (!nspace.IsEmpty()) {
nsId = txNamespaceManager::getNamespaceID(nspace);
NS_ENSURE_FALSE(nsId == kNameSpaceID_Unknown,
NS_ERROR_FAILURE);
}
}
else if (prefix) {
nsId = mMappings->lookupNamespace(prefix);
if (nsId == kNameSpaceID_Unknown) {
// tunkate name to indicate failure
name.Truncate();
}
if (!nspace.IsEmpty()) {
nsId = txNamespaceManager::getNamespaceID(nspace);
}
}
if (prefix == txXMLAtoms::xmlns) {
// Cut xmlns: (6 characters)
name.Cut(0, 6);
else if (colon) {
nsId = mMappings->lookupNamespace(prefix);
}
nsAutoPtr<txTextHandler> handler(
NS_STATIC_CAST(txTextHandler*, aEs.popResultHandler()));
if (!name.IsEmpty()) {
// add attribute if everything was ok
return aEs.mResultHandler->attribute(name, nsId, handler->mValue);
}
return NS_OK;
// add attribute if everything was ok
return nsId != kNameSpaceID_Unknown ?
aEs.mResultHandler->attribute(prefix, Substring(name, lnameStart),
nsId, handler->mValue) :
NS_OK;
}
txCallTemplate::txCallTemplate(const txExpandedName& aName)
@ -272,12 +260,16 @@ txCopyBase::copyNode(const txXPathNode& aNode, txExecutionState& aEs)
switch (txXPathNodeUtils::getNodeType(aNode)) {
case txXPathNodeType::ATTRIBUTE_NODE:
{
nsAutoString nodeName, nodeValue;
txXPathNodeUtils::getNodeName(aNode, nodeName);
nsAutoString nodeValue;
txXPathNodeUtils::appendNodeValue(aNode, nodeValue);
nsCOMPtr<nsIAtom> localName =
txXPathNodeUtils::getLocalName(aNode);
return aEs.mResultHandler->
attribute(nodeName, txXPathNodeUtils::getNamespaceID(aNode),
nodeValue);
attribute(txXPathNodeUtils::getPrefix(aNode),
localName, nsnull,
txXPathNodeUtils::getNamespaceID(aNode),
nodeValue);
}
case txXPathNodeType::COMMENT_NODE:
{
@ -299,21 +291,28 @@ txCopyBase::copyNode(const txXPathNode& aNode, txExecutionState& aEs)
}
case txXPathNodeType::ELEMENT_NODE:
{
nsAutoString name;
txXPathNodeUtils::getNodeName(aNode, name);
PRInt32 nsID = txXPathNodeUtils::getNamespaceID(aNode);
nsresult rv = aEs.mResultHandler->startElement(name, nsID);
nsCOMPtr<nsIAtom> localName =
txXPathNodeUtils::getLocalName(aNode);
nsresult rv = aEs.mResultHandler->
startElement(txXPathNodeUtils::getPrefix(aNode),
localName, nsnull,
txXPathNodeUtils::getNamespaceID(aNode));
NS_ENSURE_SUCCESS(rv, rv);
// Copy attributes
txXPathTreeWalker walker(aNode);
if (walker.moveToFirstAttribute()) {
do {
nsAutoString nodeName, nodeValue;
walker.getNodeName(nodeName);
nsAutoString nodeValue;
walker.appendNodeValue(nodeValue);
const txXPathNode& attr = walker.getCurrentPosition();
localName = txXPathNodeUtils::getLocalName(attr);
rv = aEs.mResultHandler->
attribute(nodeName, walker.getNamespaceID(), nodeValue);
attribute(txXPathNodeUtils::getPrefix(attr),
localName, nsnull,
txXPathNodeUtils::getNamespaceID(attr),
nodeValue);
NS_ENSURE_SUCCESS(rv, rv);
} while (walker.moveToNextAttribute());
walker.moveToParent();
@ -326,7 +325,7 @@ txCopyBase::copyNode(const txXPathNode& aNode, txExecutionState& aEs)
hasChild = walker.moveToNextSibling();
}
return aEs.mResultHandler->endElement(name, nsID);
return aEs.mResultHandler->endElement();
}
case txXPathNodeType::PROCESSING_INSTRUCTION_NODE:
{
@ -367,28 +366,24 @@ txCopy::execute(txExecutionState& aEs)
rv = aEs.mResultHandler->characters(empty, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
rv = aEs.pushString(empty);
NS_ENSURE_SUCCESS(rv, rv);
rv = aEs.pushInt(kNameSpaceID_None);
rv = aEs.pushBool(PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
break;
}
case txXPathNodeType::ELEMENT_NODE:
{
nsAutoString nodeName;
txXPathNodeUtils::getNodeName(node, nodeName);
PRInt32 nsID = txXPathNodeUtils::getNamespaceID(node);
rv = aEs.mResultHandler->startElement(nodeName, nsID);
nsCOMPtr<nsIAtom> localName =
txXPathNodeUtils::getLocalName(node);
nsresult rv = aEs.mResultHandler->
startElement(txXPathNodeUtils::getPrefix(node),
localName, nsnull,
txXPathNodeUtils::getNamespaceID(node));
NS_ENSURE_SUCCESS(rv, rv);
// XXX copy namespace nodes once we have them
rv = aEs.pushString(nodeName);
NS_ENSURE_SUCCESS(rv, rv);
rv = aEs.pushInt(nsID);
rv = aEs.pushBool(PR_TRUE);
NS_ENSURE_SUCCESS(rv, rv);
break;
@ -455,14 +450,11 @@ txCopyOf::execute(txExecutionState& aEs)
nsresult
txEndElement::execute(txExecutionState& aEs)
{
PRInt32 namespaceID = aEs.popInt();
nsAutoString nodeName;
aEs.popString(nodeName);
// For xsl:elements with a bad name we push an empty name
if (!nodeName.IsEmpty()) {
return aEs.mResultHandler->endElement(nodeName, namespaceID);
// This will return false if startElement was not called. This happens
// when <xsl:element> produces a bad name, or when <xsl:copy> copies a
// document node.
if (aEs.popBool()) {
return aEs.mResultHandler->endElement();
}
return NS_OK;
@ -535,24 +527,14 @@ txLREAttribute::txLREAttribute(PRInt32 aNamespaceID, nsIAtom* aLocalName,
mPrefix(aPrefix),
mValue(aValue)
{
if (aNamespaceID == kNameSpaceID_None) {
mLowercaseLocalName = TX_ToLowerCaseAtom(aLocalName);
}
}
nsresult
txLREAttribute::execute(txExecutionState& aEs)
{
// We should atomize the resulthandler
nsAutoString nodeName;
if (mPrefix) {
mPrefix->ToString(nodeName);
nsAutoString localName;
nodeName.Append(PRUnichar(':'));
mLocalName->ToString(localName);
nodeName.Append(localName);
}
else {
mLocalName->ToString(nodeName);
}
nsRefPtr<txAExprResult> exprRes;
nsresult rv = mValue->evaluate(aEs.getEvalContext(),
getter_AddRefs(exprRes));
@ -560,12 +542,16 @@ txLREAttribute::execute(txExecutionState& aEs)
const nsString* value = exprRes->stringValuePointer();
if (value) {
return aEs.mResultHandler->attribute(nodeName, mNamespaceID, *value);
return aEs.mResultHandler->attribute(mPrefix, mLocalName,
mLowercaseLocalName,
mNamespaceID, *value);
}
nsAutoString valueStr;
exprRes->stringValue(valueStr);
return aEs.mResultHandler->attribute(nodeName, mNamespaceID, valueStr);
return aEs.mResultHandler->attribute(mPrefix, mLocalName,
mLowercaseLocalName,
mNamespaceID, valueStr);
}
txMessage::txMessage(PRBool aTerminate)
@ -886,14 +872,18 @@ txStartElement::execute(txExecutionState& aEs)
nsresult rv = mName->evaluateToString(aEs.getEvalContext(), name);
NS_ENSURE_SUCCESS(rv, rv);
const PRUnichar* colon;
if (!XMLUtils::isValidQName(name, &colon)) {
// truncate name to indicate failure
name.Truncate();
}
PRInt32 nsId = kNameSpaceID_None;
if (!name.IsEmpty()) {
nsCOMPtr<nsIAtom> prefix;
PRUint32 lnameStart = 0;
const PRUnichar* colon;
if (XMLUtils::isValidQName(name, &colon)) {
if (colon) {
prefix = do_GetAtom(Substring(name.get(), colon));
lnameStart = colon - name.get() + 1;
}
if (mNamespace) {
nsAutoString nspace;
rv = mNamespace->evaluateToString(aEs.getEvalContext(),
@ -902,38 +892,36 @@ txStartElement::execute(txExecutionState& aEs)
if (!nspace.IsEmpty()) {
nsId = txNamespaceManager::getNamespaceID(nspace);
NS_ENSURE_FALSE(nsId == kNameSpaceID_Unknown,
NS_ERROR_FAILURE);
}
}
else {
nsCOMPtr<nsIAtom> prefix;
if (colon) {
prefix = do_GetAtom(Substring(name.get(), colon));
}
nsId = mMappings->lookupNamespace(prefix);
if (nsId == kNameSpaceID_Unknown) {
// truncate name to indicate failure
name.Truncate();
}
}
}
else {
nsId = kNameSpaceID_Unknown;
}
if (!name.IsEmpty()) {
// add element if everything was ok
rv = aEs.mResultHandler->startElement(name, nsId);
PRBool success = PR_TRUE;
if (nsId != kNameSpaceID_Unknown) {
rv = aEs.mResultHandler->startElement(prefix,
Substring(name, lnameStart),
nsId);
}
else {
rv = NS_ERROR_XSLT_BAD_NODE_NAME;
}
if (rv == NS_ERROR_XSLT_BAD_NODE_NAME) {
success = PR_FALSE;
// we call characters with an empty string to "close" any element to
// make sure that no attributes are added
rv = aEs.mResultHandler->characters(EmptyString(), PR_FALSE);
}
NS_ENSURE_SUCCESS(rv, rv);
rv = aEs.pushString(name);
NS_ENSURE_SUCCESS(rv, rv);
rv = aEs.pushInt(nsId);
rv = aEs.pushBool(success);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
@ -947,31 +935,20 @@ txStartLREElement::txStartLREElement(PRInt32 aNamespaceID,
mLocalName(aLocalName),
mPrefix(aPrefix)
{
if (aNamespaceID == kNameSpaceID_None) {
mLowercaseLocalName = TX_ToLowerCaseAtom(aLocalName);
}
}
nsresult
txStartLREElement::execute(txExecutionState& aEs)
{
// We should atomize the resulthandler
nsAutoString nodeName;
if (mPrefix) {
mPrefix->ToString(nodeName);
nsAutoString localName;
nodeName.Append(PRUnichar(':'));
mLocalName->ToString(localName);
nodeName.Append(localName);
}
else {
mLocalName->ToString(nodeName);
}
nsresult rv = aEs.mResultHandler->startElement(nodeName, mNamespaceID);
nsresult rv = aEs.mResultHandler->startElement(mPrefix, mLocalName,
mLowercaseLocalName,
mNamespaceID);
NS_ENSURE_SUCCESS(rv, rv);
rv = aEs.pushString(nodeName);
NS_ENSURE_SUCCESS(rv, rv);
rv = aEs.pushInt(mNamespaceID);
rv = aEs.pushBool(PR_TRUE);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;

View File

@ -228,6 +228,7 @@ public:
PRInt32 mNamespaceID;
nsCOMPtr<nsIAtom> mLocalName;
nsCOMPtr<nsIAtom> mLowercaseLocalName;
nsCOMPtr<nsIAtom> mPrefix;
nsAutoPtr<Expr> mValue;
};
@ -396,6 +397,7 @@ public:
PRInt32 mNamespaceID;
nsCOMPtr<nsIAtom> mLocalName;
nsCOMPtr<nsIAtom> mLowercaseLocalName;
nsCOMPtr<nsIAtom> mPrefix;
};

View File

@ -52,8 +52,9 @@
#include "nsICharsetAlias.h"
#include "nsIPrincipal.h"
#include "txURIUtils.h"
static NS_DEFINE_CID(kXMLDocumentCID, NS_XMLDOCUMENT_CID);
#include "nsContentCreatorFunctions.h"
#include "nsContentUtils.h"
#include "nsGkAtoms.h"
txMozillaTextOutput::txMozillaTextOutput(nsIDOMDocument* aSourceDocument,
nsIDOMDocument* aResultDocument,
@ -65,23 +66,8 @@ txMozillaTextOutput::txMozillaTextOutput(nsIDOMDocument* aSourceDocument,
txMozillaTextOutput::txMozillaTextOutput(nsIDOMDocumentFragment* aDest)
{
nsCOMPtr<nsIDOMDocument> doc;
aDest->GetOwnerDocument(getter_AddRefs(doc));
NS_ASSERTION(doc, "unable to get ownerdocument");
nsCOMPtr<nsIDOMText> textNode;
nsresult rv = doc->CreateTextNode(EmptyString(),
getter_AddRefs(textNode));
if (NS_FAILED(rv)) {
return;
}
nsCOMPtr<nsIDOMNode> dummy;
rv = aDest->AppendChild(textNode, getter_AddRefs(dummy));
if (NS_FAILED(rv)) {
return;
}
mTextNode = textNode;
return;
mTextParent = do_QueryInterface(aDest);
mDocument = mTextParent->GetOwnerDoc();
}
txMozillaTextOutput::~txMozillaTextOutput()
@ -89,24 +75,31 @@ txMozillaTextOutput::~txMozillaTextOutput()
}
nsresult
txMozillaTextOutput::attribute(const nsAString& aName,
txMozillaTextOutput::attribute(nsIAtom* aPrefix, nsIAtom* aLocalName,
nsIAtom* aLowercaseLocalName,
PRInt32 aNsID, const nsString& aValue)
{
return NS_OK;
}
nsresult
txMozillaTextOutput::attribute(nsIAtom* aPrefix, const nsSubstring& aName,
const PRInt32 aNsID,
const nsAString& aValue)
const nsString& aValue)
{
return NS_OK;
}
nsresult
txMozillaTextOutput::characters(const nsAString& aData, PRBool aDOE)
txMozillaTextOutput::characters(const nsSubstring& aData, PRBool aDOE)
{
if (mTextNode)
mTextNode->AppendData(aData);
mText.Append(aData);
return NS_OK;
}
nsresult
txMozillaTextOutput::comment(const nsAString& aData)
txMozillaTextOutput::comment(const nsString& aData)
{
return NS_OK;
}
@ -114,6 +107,17 @@ txMozillaTextOutput::comment(const nsAString& aData)
nsresult
txMozillaTextOutput::endDocument(nsresult aResult)
{
NS_ENSURE_TRUE(mDocument && mTextParent, NS_ERROR_FAILURE);
nsCOMPtr<nsIContent> text;
nsresult rv = NS_NewTextNode(getter_AddRefs(text),
mDocument->NodeInfoManager());
NS_ENSURE_SUCCESS(rv, rv);
text->SetText(mText, PR_FALSE);
rv = mTextParent->AppendChildTo(text, PR_TRUE);
NS_ENSURE_SUCCESS(rv, rv);
if (NS_SUCCEEDED(aResult)) {
nsCOMPtr<nsITransformObserver> observer = do_QueryReferent(mObserver);
if (observer) {
@ -125,15 +129,14 @@ txMozillaTextOutput::endDocument(nsresult aResult)
}
nsresult
txMozillaTextOutput::endElement(const nsAString& aName,
const PRInt32 aNsID)
txMozillaTextOutput::endElement()
{
return NS_OK;
}
nsresult
txMozillaTextOutput::processingInstruction(const nsAString& aTarget,
const nsAString& aData)
txMozillaTextOutput::processingInstruction(const nsString& aTarget,
const nsString& aData)
{
return NS_OK;
}
@ -149,14 +152,14 @@ txMozillaTextOutput::createResultDocument(nsIDOMDocument* aSourceDocument,
nsIDOMDocument* aResultDocument)
{
nsresult rv = NS_OK;
/*
* Create an XHTML document to hold the text.
*
* <html>
* <head />
* <body>
* <pre> * The text comes here * </pre>
* <pre id="transformiixResult"> * The text comes here * </pre>
* <body>
* </html>
*
@ -165,19 +168,14 @@ txMozillaTextOutput::createResultDocument(nsIDOMDocument* aSourceDocument,
*
* <transformiix:result> * The text comes here * </transformiix:result>
*/
nsCOMPtr<nsIDocument> doc;
if (!aResultDocument) {
// Create the document
doc = do_CreateInstance(kXMLDocumentCID, &rv);
rv = NS_NewXMLDocument(getter_AddRefs(mDocument));
NS_ENSURE_SUCCESS(rv, rv);
mDocument = do_QueryInterface(doc);
}
else {
mDocument = aResultDocument;
doc = do_QueryInterface(aResultDocument, &rv);
NS_ENSURE_SUCCESS(rv, rv);
mDocument = do_QueryInterface(aResultDocument);
}
NS_ASSERTION(mDocument, "Need document");
@ -188,7 +186,7 @@ txMozillaTextOutput::createResultDocument(nsIDOMDocument* aSourceDocument,
}
// Reset and set up document
URIUtils::ResetWithSource(doc, aSourceDocument);
URIUtils::ResetWithSource(mDocument, aSourceDocument);
// Set the charset
if (!mOutputFormat.mEncoding.IsEmpty()) {
@ -199,8 +197,8 @@ txMozillaTextOutput::createResultDocument(nsIDOMDocument* aSourceDocument,
if (calias &&
NS_SUCCEEDED(calias->GetPreferred(charset, canonicalCharset))) {
doc->SetDocumentCharacterSet(canonicalCharset);
doc->SetDocumentCharacterSetSource(kCharsetFromOtherComponent);
mDocument->SetDocumentCharacterSet(canonicalCharset);
mDocument->SetDocumentCharacterSetSource(kCharsetFromOtherComponent);
}
}
@ -217,77 +215,64 @@ txMozillaTextOutput::createResultDocument(nsIDOMDocument* aSourceDocument,
// observer) we only create a transformiix:result root element.
// Don't do this when called through nsIXSLTProcessorObsolete (i.e. when
// aResultDocument is set) for compability reasons
nsCOMPtr<nsIDOMNode> textContainer;
if (!aResultDocument && !observer) {
nsCOMPtr<nsIDOMElement> docElement;
rv = mDocument->CreateElementNS(NS_LITERAL_STRING(kTXNameSpaceURI),
NS_LITERAL_STRING(kTXWrapper),
getter_AddRefs(docElement));
PRInt32 namespaceID;
rv = nsContentUtils::NameSpaceManager()->
RegisterNameSpace(NS_LITERAL_STRING(kTXNameSpaceURI), namespaceID);
NS_ENSURE_SUCCESS(rv, rv);
rv = mDocument->AppendChild(docElement, getter_AddRefs(textContainer));
rv = mDocument->CreateElem(nsGkAtoms::result, nsGkAtoms::transformiix,
namespaceID, PR_FALSE, getter_AddRefs(mTextParent));
NS_ENSURE_SUCCESS(rv, rv);
rv = mDocument->AppendChildTo(mTextParent, PR_TRUE);
NS_ENSURE_SUCCESS(rv, rv);
}
else {
nsCOMPtr<nsIDOMElement> element, docElement;
nsCOMPtr<nsIDOMNode> parent, pre;
NS_NAMED_LITERAL_STRING(XHTML_NSURI, "http://www.w3.org/1999/xhtml");
rv = mDocument->CreateElementNS(XHTML_NSURI,
NS_LITERAL_STRING("html"),
getter_AddRefs(docElement));
nsCOMPtr<nsIContent> html, head, body;
rv = createXHTMLElement(nsGkAtoms::html, getter_AddRefs(html));
NS_ENSURE_SUCCESS(rv, rv);
rv = mDocument->AppendChild(docElement, getter_AddRefs(parent));
rv = createXHTMLElement(nsGkAtoms::head, getter_AddRefs(head));
NS_ENSURE_SUCCESS(rv, rv);
rv = mDocument->CreateElementNS(XHTML_NSURI,
NS_LITERAL_STRING("head"),
getter_AddRefs(element));
rv = html->AppendChildTo(head, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
rv = docElement->AppendChild(element, getter_AddRefs(parent));
rv = createXHTMLElement(nsGkAtoms::body, getter_AddRefs(body));
NS_ENSURE_SUCCESS(rv, rv);
rv = mDocument->CreateElementNS(XHTML_NSURI,
NS_LITERAL_STRING("body"),
getter_AddRefs(element));
rv = html->AppendChildTo(body, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
rv = docElement->AppendChild(element, getter_AddRefs(parent));
rv = createXHTMLElement(nsGkAtoms::pre, getter_AddRefs(mTextParent));
NS_ENSURE_SUCCESS(rv, rv);
rv = mDocument->CreateElementNS(XHTML_NSURI,
NS_LITERAL_STRING("pre"),
getter_AddRefs(element));
rv = mTextParent->SetAttr(kNameSpaceID_None, nsGkAtoms::id,
NS_LITERAL_STRING("transformiixResult"),
PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
rv = parent->AppendChild(element, getter_AddRefs(pre));
rv = body->AppendChildTo(mTextParent, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMHTMLElement> htmlElement = do_QueryInterface(pre);
htmlElement->SetId(NS_LITERAL_STRING("transformiixResult"));
rv = mDocument->AppendChildTo(html, PR_TRUE);
NS_ENSURE_SUCCESS(rv, rv);
textContainer = pre;
}
nsCOMPtr<nsIDOMText> textNode;
rv = mDocument->CreateTextNode(EmptyString(), getter_AddRefs(textNode));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMNode> dummy;
rv = textContainer->AppendChild(textNode, getter_AddRefs(dummy));
NS_ENSURE_SUCCESS(rv, rv);
mTextNode = textNode;
return NS_OK;
}
nsresult
txMozillaTextOutput::startElement(const nsAString& aName,
txMozillaTextOutput::startElement(nsIAtom* aPrefix, nsIAtom* aLocalName,
nsIAtom* aLowercaseLocalName, PRInt32 aNsID)
{
return NS_OK;
}
nsresult
txMozillaTextOutput::startElement(nsIAtom* aPrefix, const nsSubstring& aName,
const PRInt32 aNsID)
{
return NS_OK;
@ -295,6 +280,20 @@ txMozillaTextOutput::startElement(const nsAString& aName,
void txMozillaTextOutput::getOutputDocument(nsIDOMDocument** aDocument)
{
*aDocument = mDocument;
NS_IF_ADDREF(*aDocument);
CallQueryInterface(mDocument, aDocument);
}
nsresult
txMozillaTextOutput::createXHTMLElement(nsIAtom* aName,
nsIContent** aResult)
{
*aResult = nsnull;
nsCOMPtr<nsINodeInfo> ni;
nsresult rv = mDocument->NodeInfoManager()->
GetNodeInfo(aName, nsnull, kNameSpaceID_XHTML, getter_AddRefs(ni));
NS_ENSURE_SUCCESS(rv, rv);
return NS_NewHTMLElement(aResult, ni);
}

View File

@ -48,6 +48,8 @@ class nsIDOMCharacterData;
class nsIDOMDocument;
class nsIDOMDocumentFragment;
class nsITransformObserver;
class nsIDocument;
class nsIContent;
class txMozillaTextOutput : public txAOutputXMLEventHandler
{
@ -64,11 +66,13 @@ public:
private:
nsresult createResultDocument(nsIDOMDocument* aSourceDocument,
nsIDOMDocument* aResultDocument);
nsresult createXHTMLElement(nsIAtom* aName, nsIContent** aResult);
nsCOMPtr<nsIDOMCharacterData> mTextNode;
nsCOMPtr<nsIContent> mTextParent;
nsWeakPtr mObserver;
nsCOMPtr<nsIDOMDocument> mDocument;
nsCOMPtr<nsIDocument> mDocument;
txOutputFormat mOutputFormat;
nsString mText;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -55,6 +55,9 @@ class nsIDOMElement;
class nsIStyleSheet;
class nsIDOMNode;
class nsITransformObserver;
class nsNodeInfoManager;
class nsIDocument;
class nsINode;
class txTransformNotifier : public nsIScriptLoaderObserver,
public nsICSSLoaderObserver
@ -76,12 +79,12 @@ public:
nsresult AddStyleSheet(nsIStyleSheet* aStyleSheet);
void OnTransformEnd(nsresult aResult = NS_OK);
void OnTransformStart();
nsresult SetOutputDocument(nsIDOMDocument* aDocument);
nsresult SetOutputDocument(nsIDocument* aDocument);
private:
void SignalTransformEnd(nsresult aResult = NS_OK);
nsCOMPtr<nsIDOMDocument> mDocument;
nsCOMPtr<nsIDocument> mDocument;
nsCOMPtr<nsITransformObserver> mObserver;
nsCOMArray<nsIScriptElement> mScriptElements;
nsCOMArray<nsIStyleSheet> mStylesheets;
@ -91,7 +94,7 @@ private:
class txMozillaXMLOutput : public txAOutputXMLEventHandler
{
public:
txMozillaXMLOutput(const nsAString& aRootName,
txMozillaXMLOutput(const nsSubstring& aRootName,
PRInt32 aRootNsID,
txOutputFormat* aFormat,
nsIDOMDocument* aSourceDocument,
@ -105,23 +108,34 @@ public:
TX_DECL_TXAOUTPUTXMLEVENTHANDLER
private:
nsresult closePrevious(PRInt8 aAction);
nsresult closePrevious(PRBool aFlushText);
nsresult createTxWrapper();
nsresult startHTMLElement(nsIDOMElement* aElement, PRBool aXHTML);
nsresult endHTMLElement(nsIDOMElement* aElement);
void processHTTPEquiv(nsIAtom* aHeader, const nsAString& aValue);
nsresult createResultDocument(const nsAString& aName, PRInt32 aNsID,
nsresult startHTMLElement(nsIContent* aElement, PRBool aXHTML);
nsresult endHTMLElement(nsIContent* aElement);
void processHTTPEquiv(nsIAtom* aHeader, const nsString& aValue);
nsresult createResultDocument(const nsSubstring& aName, PRInt32 aNsID,
nsIDOMDocument* aSourceDocument,
nsIDOMDocument* aResultDocument);
nsresult createHTMLElement(const nsAString& aName,
nsIDOMElement** aResult);
nsresult createHTMLElement(nsIAtom* aName,
nsIContent** aResult);
nsCOMPtr<nsIDOMDocument> mDocument;
nsCOMPtr<nsIDOMNode> mCurrentNode;
nsCOMPtr<nsIDOMNode> mParentNode;
nsresult attributeInternal(nsIAtom* aPrefix, nsIAtom* aLocalName,
PRInt32 aNsID, const nsString& aValue);
nsresult startElementInternal(nsIAtom* aPrefix, nsIAtom* aLocalName,
PRInt32 aNsID, PRInt32 aElemType);
nsCOMPtr<nsIDOMNode> mNonAddedParent;
nsCOMPtr<nsIDOMNode> mNonAddedNode;
nsCOMPtr<nsIDocument> mDocument;
nsCOMPtr<nsINode> mCurrentNode; // This is updated once an element is
// 'closed' (i.e. once we're done
// adding attributes to it).
// until then the opened element is
// kept in mOpenedElement
nsCOMPtr<nsIContent> mOpenedElement;
nsRefPtr<nsNodeInfoManager> mNodeInfoManager;
nsCOMArray<nsINode> mCurrentNodeStack;
nsCOMPtr<nsIContent> mNonAddedNode;
nsRefPtr<txTransformNotifier> mNotifier;
@ -129,7 +143,7 @@ private:
nsCString mRefreshString;
txStack mTableStateStack;
enum TableState {
enum TableState {
NORMAL, // An element needing no special treatment
TABLE, // A HTML table element
ADDED_TBODY // An inserted tbody not coming from the stylesheet
@ -145,9 +159,10 @@ private:
PRPackedBool mHaveTitleElement;
PRPackedBool mHaveBaseElement;
PRPackedBool mDocumentIsHTML;
PRPackedBool mCreatingNewDocument;
PRPackedBool mOpenedElementIsHTML;
// Set to true when we know there's a root content in our document.
PRPackedBool mRootContentCreated;

View File

@ -151,7 +151,7 @@ txToDocHandlerFactory::createHandlerWith(txOutputFormat* aFormat,
nsresult
txToDocHandlerFactory::createHandlerWith(txOutputFormat* aFormat,
const nsAString& aName,
const nsSubstring& aName,
PRInt32 aNsID,
txAXMLEventHandler** aHandler)
{
@ -229,7 +229,7 @@ txToFragmentHandlerFactory::createHandlerWith(txOutputFormat* aFormat,
nsresult
txToFragmentHandlerFactory::createHandlerWith(txOutputFormat* aFormat,
const nsAString& aName,
const nsSubstring& aName,
PRInt32 aNsID,
txAXMLEventHandler** aHandler)
{
@ -1165,7 +1165,7 @@ txMozillaXSLTProcessor::notifyError()
}
}
mObserver->OnTransformDone(mTransformResult, errorDocument);
mObserver->OnTransformDone(mTransformResult, document);
}
nsresult

View File

@ -49,15 +49,23 @@ txTextHandler::~txTextHandler()
}
nsresult
txTextHandler::attribute(const nsAString& aName,
const PRInt32 aNsID,
const nsAString& aValue)
txTextHandler::attribute(nsIAtom* aPrefix, nsIAtom* aLocalName,
nsIAtom* aLowercaseLocalName, PRInt32 aNsID,
const nsString& aValue)
{
return NS_OK;
}
nsresult
txTextHandler::characters(const nsAString& aData, PRBool aDOE)
txTextHandler::attribute(nsIAtom* aPrefix, const nsSubstring& aLocalName,
const PRInt32 aNsID,
const nsString& aValue)
{
return NS_OK;
}
nsresult
txTextHandler::characters(const nsSubstring& aData, PRBool aDOE)
{
if (mLevel == 0)
mValue.Append(aData);
@ -66,7 +74,7 @@ txTextHandler::characters(const nsAString& aData, PRBool aDOE)
}
nsresult
txTextHandler::comment(const nsAString& aData)
txTextHandler::comment(const nsString& aData)
{
return NS_OK;
}
@ -78,7 +86,7 @@ txTextHandler::endDocument(nsresult aResult)
}
nsresult
txTextHandler::endElement(const nsAString& aName, const PRInt32 aNsID)
txTextHandler::endElement()
{
if (mOnlyText)
--mLevel;
@ -87,7 +95,7 @@ txTextHandler::endElement(const nsAString& aName, const PRInt32 aNsID)
}
nsresult
txTextHandler::processingInstruction(const nsAString& aTarget, const nsAString& aData)
txTextHandler::processingInstruction(const nsString& aTarget, const nsString& aData)
{
return NS_OK;
}
@ -99,7 +107,18 @@ txTextHandler::startDocument()
}
nsresult
txTextHandler::startElement(const nsAString& aName, const PRInt32 aNsID)
txTextHandler::startElement(nsIAtom* aPrefix, nsIAtom* aLocalName,
nsIAtom* aLowercaseLocalName, const PRInt32 aNsID)
{
if (mOnlyText)
++mLevel;
return NS_OK;
}
nsresult
txTextHandler::startElement(nsIAtom* aPrefix, const nsSubstring& aLocalName,
const PRInt32 aNsID)
{
if (mOnlyText)
++mLevel;

View File

@ -40,6 +40,7 @@
#include "txExecutionState.h"
#include "txStringUtils.h"
#include "txStylesheet.h"
#include "txAtoms.h"
txUnknownHandler::txUnknownHandler(txExecutionState* aEs)
: mEs(aEs)
@ -50,18 +51,6 @@ txUnknownHandler::~txUnknownHandler()
{
}
nsresult
txUnknownHandler::attribute(const nsAString& aName,
const PRInt32 aNsID,
const nsAString& aValue)
{
// If this is called then the stylesheet is trying to add an attribute
// without adding an element first. So we'll just ignore it.
// XXX ErrorReport: Signal this?
return NS_OK;
}
nsresult
txUnknownHandler::endDocument(nsresult aResult)
{
@ -79,7 +68,7 @@ txUnknownHandler::endDocument(nsresult aResult)
NS_ASSERTION(mEs->mResultHandler == this,
"We're leaking mEs->mResultHandler and are going to crash.");
nsresult rv = createHandlerAndFlush(eXMLOutput, EmptyString(),
nsresult rv = createHandlerAndFlush(PR_FALSE, EmptyString(),
kNameSpaceID_None);
NS_ENSURE_SUCCESS(rv, rv);
@ -91,7 +80,8 @@ txUnknownHandler::endDocument(nsresult aResult)
}
nsresult
txUnknownHandler::startElement(const nsAString& aName, const PRInt32 aNsID)
txUnknownHandler::startElement(nsIAtom* aPrefix, nsIAtom* aLocalName,
nsIAtom* aLowercaseLocalName, PRInt32 aNsID)
{
// Make sure that mEs->mResultHandler == this is true, otherwise we'll
// leak mEs->mResultHandler in createHandlerAndFlush and we may crash
@ -99,37 +89,67 @@ txUnknownHandler::startElement(const nsAString& aName, const PRInt32 aNsID)
NS_ASSERTION(mEs->mResultHandler == this,
"We're leaking mEs->mResultHandler.");
nsresult rv = NS_OK;
txOutputFormat* format = mEs->mStylesheet->getOutputFormat();
if (format->mMethod != eMethodNotSet) {
rv = createHandlerAndFlush(format->mMethod, aName, aNsID);
}
else if (aNsID == kNameSpaceID_None &&
aName.Equals(NS_LITERAL_STRING("html"),
txCaseInsensitiveStringComparator())) {
rv = createHandlerAndFlush(eHTMLOutput, aName, aNsID);
}
else {
rv = createHandlerAndFlush(eXMLOutput, aName, aNsID);
nsCOMPtr<nsIAtom> owner;
if (!aLowercaseLocalName) {
owner = TX_ToLowerCaseAtom(aLocalName);
NS_ENSURE_TRUE(owner, NS_ERROR_OUT_OF_MEMORY);
aLowercaseLocalName = owner;
}
PRBool htmlRoot = aNsID == kNameSpaceID_None && !aPrefix &&
aLowercaseLocalName == txHTMLAtoms::html;
// Use aLocalName and not aLowercaseLocalName in case the output
// handler cares about case. For eHTMLOutput the handler will hardcode
// to 'html' anyway.
nsAutoString name;
aLocalName->ToString(name);
nsresult rv = createHandlerAndFlush(htmlRoot, name, aNsID);
NS_ENSURE_SUCCESS(rv, rv);
rv = mEs->mResultHandler->startElement(aName, aNsID);
rv = mEs->mResultHandler->startElement(aPrefix, aLocalName,
aLowercaseLocalName, aNsID);
delete this;
return rv;
}
nsresult txUnknownHandler::createHandlerAndFlush(txOutputMethod aMethod,
const nsAString& aName,
nsresult
txUnknownHandler::startElement(nsIAtom* aPrefix, const nsSubstring& aLocalName,
const PRInt32 aNsID)
{
// Make sure that mEs->mResultHandler == this is true, otherwise we'll
// leak mEs->mResultHandler in createHandlerAndFlush and we may crash
// later on trying to delete this handler again.
NS_ASSERTION(mEs->mResultHandler == this,
"We're leaking mEs->mResultHandler.");
PRBool htmlRoot = aNsID == kNameSpaceID_None && !aPrefix &&
aLocalName.Equals(NS_LITERAL_STRING("html"),
txCaseInsensitiveStringComparator());
nsresult rv = createHandlerAndFlush(htmlRoot, aLocalName, aNsID);
NS_ENSURE_SUCCESS(rv, rv);
rv = mEs->mResultHandler->startElement(aPrefix, aLocalName, aNsID);
delete this;
return rv;
}
nsresult txUnknownHandler::createHandlerAndFlush(PRBool aHTMLRoot,
const nsSubstring& aName,
const PRInt32 aNsID)
{
NS_ENSURE_TRUE(mBuffer, NS_ERROR_NOT_INITIALIZED);
txOutputFormat format;
format.merge(*mEs->mStylesheet->getOutputFormat());
format.mMethod = aMethod;
format.merge(*(mEs->mStylesheet->getOutputFormat()));
if (format.mMethod == eMethodNotSet) {
format.mMethod = aHTMLRoot ? eHTMLOutput : eXMLOutput;
}
txAXMLEventHandler *handler = nsnull;
nsresult rv = mEs->mOutputHandlerFactory->createHandlerWith(&format, aName,

View File

@ -50,14 +50,15 @@ public:
txUnknownHandler(txExecutionState* aEs);
virtual ~txUnknownHandler();
nsresult attribute(const nsAString& aName, const PRInt32 aNsID,
const nsAString& aValue);
nsresult endDocument(nsresult aResult);
nsresult startElement(const nsAString& aName, const PRInt32 aNsID);
nsresult startElement(nsIAtom* aPrefix, nsIAtom* aName,
nsIAtom* aLowercaseName, PRInt32 aNsID);
nsresult startElement(nsIAtom* aPrefix, const nsSubstring& aLocalName,
const PRInt32 aNsID);
private:
nsresult createHandlerAndFlush(txOutputMethod aMethod,
const nsAString& aName,
nsresult createHandlerAndFlush(PRBool aHTMLRoot,
const nsSubstring& aName,
const PRInt32 aNsID);
/*

View File

@ -40,6 +40,7 @@
#define TRANSFRMX_XML_EVENT_HANDLER_H
#include "txCore.h"
#include "nsIAtom.h"
class txOutputFormat;
@ -65,13 +66,28 @@ public:
/**
* Signals to receive the start of an attribute.
*
* @param aName the name of the attribute
* @param aPrefix the prefix of the attribute
* @param aLocalName the localname of the attribute
* @param aLowercaseName the localname of the attribute in lower case
* @param aNsID the namespace ID of the attribute
* @param aValue the value of the attribute
*/
virtual nsresult attribute(const nsAString& aName,
virtual nsresult attribute(nsIAtom* aPrefix, nsIAtom* aLocalName,
nsIAtom* aLowercaseLocalName, PRInt32 aNsID,
const nsString& aValue) = 0;
/**
* Signals to receive the start of an attribute.
*
* @param aPrefix the prefix of the attribute
* @param aLocalName the localname of the attribute
* @param aNsID the namespace ID of the attribute
* @param aValue the value of the attribute
*/
virtual nsresult attribute(nsIAtom* aPrefix,
const nsSubstring& aLocalName,
const PRInt32 aNsID,
const nsAString& aValue) = 0;
const nsString& aValue) = 0;
/**
* Signals to receive characters.
@ -79,14 +95,14 @@ public:
* @param aData the characters to receive
* @param aDOE disable output escaping for these characters
*/
virtual nsresult characters(const nsAString& aData, PRBool aDOE) = 0;
virtual nsresult characters(const nsSubstring& aData, PRBool aDOE) = 0;
/**
* Signals to receive data that should be treated as a comment.
*
* @param data the comment data to receive
*/
virtual nsresult comment(const nsAString& aData) = 0;
virtual nsresult comment(const nsString& aData) = 0;
/**
* Signals the end of a document. It is an error to call
@ -96,12 +112,8 @@ public:
/**
* Signals to receive the end of an element.
*
* @param aName the name of the element
* @param aNsID the namespace ID of the element
*/
virtual nsresult endElement(const nsAString& aName,
const PRInt32 aNsID) = 0;
virtual nsresult endElement() = 0;
/**
* Signals to receive a processing instruction.
@ -109,8 +121,8 @@ public:
* @param aTarget the target of the processing instruction
* @param aData the data of the processing instruction
*/
virtual nsresult processingInstruction(const nsAString& aTarget,
const nsAString& aData) = 0;
virtual nsresult processingInstruction(const nsString& aTarget,
const nsString& aData) = 0;
/**
* Signals the start of a document.
@ -120,24 +132,50 @@ public:
/**
* Signals to receive the start of an element.
*
* @param aName the name of the element
* @param aPrefix the prefix of the element
* @param aLocalName the localname of the element
* @param aLowercaseName the localname of the element in lower case
* @param aNsID the namespace ID of the element
*/
virtual nsresult startElement(const nsAString& aName,
virtual nsresult startElement(nsIAtom* aPrefix,
nsIAtom* aLocalName,
nsIAtom* aLowercaseLocalName,
PRInt32 aNsID) = 0;
/**
* Signals to receive the start of an element. Can throw
* NS_ERROR_XSLT_BAD_NODE_NAME if the name is invalid
*
* @param aPrefix the prefix of the element
* @param aLocalName the localname of the element
* @param aNsID the namespace ID of the element
*/
virtual nsresult startElement(nsIAtom* aPrefix,
const nsSubstring& aLocalName,
const PRInt32 aNsID) = 0;
};
#define TX_DECL_TXAXMLEVENTHANDLER \
virtual nsresult attribute(const nsAString& aName, const PRInt32 aNsID, \
const nsAString& aValue); \
virtual nsresult characters(const nsAString& aData, PRBool aDOE); \
virtual nsresult comment(const nsAString& aData); \
virtual nsresult attribute(nsIAtom* aPrefix, nsIAtom* aLocalName, \
nsIAtom* aLowercaseLocalName, PRInt32 aNsID, \
const nsString& aValue); \
virtual nsresult attribute(nsIAtom* aPrefix, \
const nsSubstring& aLocalName, \
const PRInt32 aNsID, \
const nsString& aValue); \
virtual nsresult characters(const nsSubstring& aData, PRBool aDOE); \
virtual nsresult comment(const nsString& aData); \
virtual nsresult endDocument(nsresult aResult = NS_OK); \
virtual nsresult endElement(const nsAString& aName, const PRInt32 aNsID);\
virtual nsresult processingInstruction(const nsAString& aTarget, \
const nsAString& aData); \
virtual nsresult endElement(); \
virtual nsresult processingInstruction(const nsString& aTarget, \
const nsString& aData); \
virtual nsresult startDocument(); \
virtual nsresult startElement(const nsAString& aName, \
virtual nsresult startElement(nsIAtom* aPrefix, \
nsIAtom* aLocalName, \
nsIAtom* aLowercaseLocalName, \
PRInt32 aNsID); \
virtual nsresult startElement(nsIAtom* aPrefix, \
const nsSubstring& aName, \
const PRInt32 aNsID);
@ -187,7 +225,7 @@ public:
*/
virtual nsresult
createHandlerWith(txOutputFormat* aFormat,
const nsAString& aName,
const nsSubstring& aName,
PRInt32 aNsID,
txAXMLEventHandler** aHandler) = 0;
};
@ -196,7 +234,7 @@ public:
nsresult createHandlerWith(txOutputFormat* aFormat, \
txAXMLEventHandler** aHandler); \
nsresult createHandlerWith(txOutputFormat* aFormat, \
const nsAString& aName, \
const nsSubstring& aName, \
PRInt32 aNsID, \
txAXMLEventHandler** aHandler);