diff --git a/mozilla/content/html/content/src/nsHTMLAtomList.h b/mozilla/content/html/content/src/nsHTMLAtomList.h index bce521e3155..ee24e6932dc 100644 --- a/mozilla/content/html/content/src/nsHTMLAtomList.h +++ b/mozilla/content/html/content/src/nsHTMLAtomList.h @@ -213,6 +213,7 @@ HTML_ATOM(msthemecompatible, "msthemecompatible") HTML_ATOM(multicol, "multicol") HTML_ATOM(multiple, "multiple") HTML_ATOM(name, "name") +HTML_ATOM(_namespace, "namespace") HTML_ATOM(noembed, "noembed") HTML_ATOM(noframes, "noframes") HTML_ATOM(nohref, "nohref") @@ -234,6 +235,7 @@ HTML_ATOM(phase, "phase") //XML Events HTML_ATOM(plaintext, "plaintext") HTML_ATOM(pointSize, "point-size") HTML_ATOM(pre, "pre") +HTML_ATOM(prefix, "prefix") HTML_ATOM(profile, "profile") HTML_ATOM(prompt, "prompt") HTML_ATOM(propagate, "propagate") //XML Events diff --git a/mozilla/content/xml/document/src/nsXMLContentSink.cpp b/mozilla/content/xml/document/src/nsXMLContentSink.cpp index d490b4b569e..eab41385c47 100644 --- a/mozilla/content/xml/document/src/nsXMLContentSink.cpp +++ b/mozilla/content/xml/document/src/nsXMLContentSink.cpp @@ -96,6 +96,7 @@ #include "nsContentCreatorFunctions.h" #include "nsIContentPolicy.h" #include "nsContentPolicyUtils.h" +#include "nsIDOMProcessingInstruction.h" #ifdef MOZ_SVG #include "nsSVGAtoms.h" @@ -230,6 +231,50 @@ nsXMLContentSink::MaybePrettyPrint() return printer->PrettyPrint(mDocument); } +static void +CheckXSLTParamPI(nsIDOMProcessingInstruction* aPi, + nsIDocumentTransformer* aProcessor, + nsIDocument* aDocument) +{ + nsAutoString target, data; + aPi->GetTarget(target); + + nsCOMPtr proc = do_QueryInterface(aProcessor); + + // Check for namespace declarations + if (target.EqualsLiteral("xslt-param-namespace")) { + aPi->GetData(data); + nsAutoString prefix, namespaceAttr; + nsParserUtils::GetQuotedAttributeValue(data, nsHTMLAtoms::prefix, + prefix); + if (!prefix.IsEmpty() && + nsParserUtils::GetQuotedAttributeValue(data, nsHTMLAtoms::_namespace, + namespaceAttr)) { + proc->AddXSLTParamNamespace(prefix, namespaceAttr); + } + } + + // Check for actual parameters + else if (target.EqualsLiteral("xslt-param")) { + aPi->GetData(data); + nsAutoString name, namespaceAttr, select, value; + nsParserUtils::GetQuotedAttributeValue(data, nsHTMLAtoms::name, + name); + nsParserUtils::GetQuotedAttributeValue(data, nsHTMLAtoms::_namespace, + namespaceAttr); + if (!nsParserUtils::GetQuotedAttributeValue(data, nsHTMLAtoms::select, select)) { + select.SetIsVoid(PR_TRUE); + } + if (!nsParserUtils::GetQuotedAttributeValue(data, nsHTMLAtoms::value, value)) { + value.SetIsVoid(PR_TRUE); + } + if (!name.IsEmpty()) { + nsCOMPtr doc = do_QueryInterface(aDocument); + proc->AddXSLTParam(name, namespaceAttr, select, value, doc); + } + } +} + NS_IMETHODIMP nsXMLContentSink::DidBuildModel() { @@ -239,6 +284,21 @@ nsXMLContentSink::DidBuildModel() } if (mXSLTProcessor) { + + // Check for xslt-param and xslt-param-namespace PIs + PRUint32 i; + nsIContent* child; + for (i = 0; (child = mDocument->GetChildAt(i)); ++i) { + if (child->IsContentOfType(nsIContent::ePROCESSING_INSTRUCTION)) { + nsCOMPtr pi = do_QueryInterface(child); + CheckXSLTParamPI(pi, mXSLTProcessor, mDocument); + } + else if (child->IsContentOfType(nsIContent::eELEMENT)) { + // Only honor PIs in the prolog + break; + } + } + nsCOMPtr currentDOMDoc(do_QueryInterface(mDocument)); mXSLTProcessor->SetSourceContentModel(currentDOMDoc); // Since the processor now holds a reference to us we drop our reference diff --git a/mozilla/content/xsl/public/nsIDocumentTransformer.h b/mozilla/content/xsl/public/nsIDocumentTransformer.h index fd6646741dc..5018484b53c 100644 --- a/mozilla/content/xsl/public/nsIDocumentTransformer.h +++ b/mozilla/content/xsl/public/nsIDocumentTransformer.h @@ -80,4 +80,22 @@ public: NS_IMETHOD CancelLoads() = 0; }; +#define NS_IDOCUMENTTRANSFORMER18BRANCH_IID \ + {0xf361a1c4, 0x6668, 0x4b0f, \ + { 0x84, 0x77, 0x24, 0x51, 0x65, 0xaa, 0x33, 0xd0 }} + +class nsIDocumentTransformer_1_8_BRANCH : public nsISupports +{ +public: + NS_DEFINE_STATIC_IID_ACCESSOR(NS_IDOCUMENTTRANSFORMER18BRANCH_IID) + + NS_IMETHOD AddXSLTParamNamespace(const nsString& aPrefix, + const nsString& aNamespace) = 0; + NS_IMETHOD AddXSLTParam(const nsString& aName, + const nsString& aNamespace, + const nsString& aValue, + const nsString& aSelect, + nsIDOMNode* aContextNode) = 0; +}; + #endif //nsIDocumentTransformer_h__ diff --git a/mozilla/extensions/transformiix/source/base/txNamespaceMap.cpp b/mozilla/extensions/transformiix/source/base/txNamespaceMap.cpp index b40871900f3..077cb64d6b9 100644 --- a/mozilla/extensions/transformiix/source/base/txNamespaceMap.cpp +++ b/mozilla/extensions/transformiix/source/base/txNamespaceMap.cpp @@ -51,12 +51,24 @@ txNamespaceMap::txNamespaceMap(const txNamespaceMap& aOther) } nsresult -txNamespaceMap::addNamespace(nsIAtom* aPrefix, const nsAString& aNamespaceURI) +txNamespaceMap::mapNamespace(nsIAtom* aPrefix, const nsAString& aNamespaceURI) { - nsIAtom* prefix = aPrefix == txXMLAtoms::_empty ? 0 : aPrefix; + nsIAtom* prefix = aPrefix == txXMLAtoms::_empty ? nsnull : aPrefix; PRInt32 nsId; - if (!prefix && aNamespaceURI.IsEmpty()) { + if (prefix && aNamespaceURI.IsEmpty()) { + // Remove the mapping + PRInt32 index = mPrefixes.IndexOf(prefix); + if (index >= 0) { + mPrefixes.RemoveObjectAt(index); + mNamespaces.RemoveElementAt(index); + } + + return NS_OK; + } + + if (aNamespaceURI.IsEmpty()) { + // Set default to empty namespace nsId = kNameSpaceID_None; } else { diff --git a/mozilla/extensions/transformiix/source/base/txNamespaceMap.h b/mozilla/extensions/transformiix/source/base/txNamespaceMap.h index 040ab8a0bfc..766d709daf4 100644 --- a/mozilla/extensions/transformiix/source/base/txNamespaceMap.h +++ b/mozilla/extensions/transformiix/source/base/txNamespaceMap.h @@ -62,7 +62,7 @@ public: return mRefCnt; } - nsresult addNamespace(nsIAtom* aPrefix, const nsAString& aNamespaceURI); + nsresult mapNamespace(nsIAtom* aPrefix, const nsAString& aNamespaceURI); PRInt32 lookupNamespace(nsIAtom* aPrefix); PRInt32 lookupNamespace(const nsAString& aPrefix); PRInt32 lookupNamespaceWithDefault(const nsAString& aPrefix); diff --git a/mozilla/extensions/transformiix/source/xslt/txMozillaXSLTProcessor.cpp b/mozilla/extensions/transformiix/source/xslt/txMozillaXSLTProcessor.cpp index 232aef26598..7ec35e3f88a 100644 --- a/mozilla/extensions/transformiix/source/xslt/txMozillaXSLTProcessor.cpp +++ b/mozilla/extensions/transformiix/source/xslt/txMozillaXSLTProcessor.cpp @@ -65,6 +65,7 @@ #include "nsIPrincipal.h" #include "jsapi.h" #include "nsIEventQueueService.h" +#include "ExprParser.h" static NS_DEFINE_CID(kXMLDocumentCID, NS_XMLDOCUMENT_CID); @@ -249,6 +250,7 @@ NS_INTERFACE_MAP_BEGIN(txMozillaXSLTProcessor) NS_INTERFACE_MAP_ENTRY(nsIXSLTProcessor) NS_INTERFACE_MAP_ENTRY(nsIXSLTProcessorObsolete) NS_INTERFACE_MAP_ENTRY(nsIDocumentTransformer) + NS_INTERFACE_MAP_ENTRY(nsIDocumentTransformer_1_8_BRANCH) NS_INTERFACE_MAP_ENTRY(nsIDocumentObserver) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXSLTProcessor) NS_INTERFACE_MAP_ENTRY_EXTERNAL_DOM_CLASSINFO(XSLTProcessor) @@ -323,6 +325,153 @@ txMozillaXSLTProcessor::SetSourceContentModel(nsIDOMNode* aSourceDOM) return NS_OK; } +NS_IMETHODIMP +txMozillaXSLTProcessor::AddXSLTParamNamespace(const nsString& aPrefix, + const nsString& aNamespace) +{ + nsCOMPtr pre = do_GetAtom(aPrefix); + return mParamNamespaceMap.mapNamespace(pre, aNamespace); +} + + +class txXSLTParamContext : public txIParseContext, + public txIEvalContext +{ +public: + txXSLTParamContext(txNamespaceMap *aResolver, txXPathNode& aContext, + txResultRecycler* aRecycler) + : mResolver(aResolver), + mContext(aContext), + mRecycler(aRecycler) + { + } + + // txIParseContext + nsresult resolveNamespacePrefix(nsIAtom* aPrefix, PRInt32& aID) + { + aID = mResolver->lookupNamespace(aPrefix); + return aID == kNameSpaceID_Unknown ? NS_ERROR_DOM_NAMESPACE_ERR : + NS_OK; + } + nsresult resolveFunctionCall(nsIAtom* aName, PRInt32 aID, + FunctionCall*& aFunction) + { + return NS_ERROR_XPATH_UNKNOWN_FUNCTION; + } + PRBool caseInsensitiveNameTests() + { + return PR_FALSE; + } + void SetErrorOffset(PRUint32 aOffset) + { + } + + // txIEvalContext + nsresult getVariable(PRInt32 aNamespace, nsIAtom* aLName, + txAExprResult*& aResult) + { + aResult = nsnull; + return NS_ERROR_INVALID_ARG; + } + PRBool isStripSpaceAllowed(const txXPathNode& aNode) + { + return PR_FALSE; + } + void* getPrivateContext() + { + return nsnull; + } + txResultRecycler* recycler() + { + return mRecycler; + } + void receiveError(const nsAString& aMsg, nsresult aRes) + { + } + const txXPathNode& getContextNode() + { + return mContext; + } + PRUint32 size() + { + return 1; + } + PRUint32 position() + { + return 1; + } + +private: + txNamespaceMap *mResolver; + txXPathNode& mContext; + txResultRecycler* mRecycler; + +}; + + +NS_IMETHODIMP +txMozillaXSLTProcessor::AddXSLTParam(const nsString& aName, + const nsString& aNamespace, + const nsString& aSelect, + const nsString& aValue, + nsIDOMNode* aContext) +{ + nsresult rv = NS_OK; + + if (aSelect.IsVoid() == aValue.IsVoid()) { + // Ignore if neither or both are specified + return NS_ERROR_FAILURE; + } + + nsRefPtr value; + if (!aSelect.IsVoid()) { + + // Set up context + nsAutoPtr contextNode( + txXPathNativeNode::createXPathNode(aContext)); + NS_ENSURE_TRUE(contextNode, NS_ERROR_OUT_OF_MEMORY); + + if (!mRecycler) { + mRecycler = new txResultRecycler; + NS_ENSURE_TRUE(mRecycler, NS_ERROR_OUT_OF_MEMORY); + } + + txXSLTParamContext paramContext(&mParamNamespaceMap, *contextNode, + mRecycler); + + // Parse + nsAutoPtr expr; + rv = txExprParser::createExpr(aSelect, ¶mContext, + getter_Transfers(expr)); + NS_ENSURE_SUCCESS(rv, rv); + + // Evaluate + rv = expr->evaluate(¶mContext, getter_AddRefs(value)); + NS_ENSURE_SUCCESS(rv, rv); + } + else { + value = new StringResult(aValue, nsnull); + NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY); + } + + nsCOMPtr name = do_GetAtom(aName); + PRInt32 nsId = txNamespaceManager::getNamespaceID(aNamespace); + NS_ENSURE_FALSE(nsId == kNameSpaceID_Unknown, NS_ERROR_FAILURE); + + txExpandedName varName(nsId, name); + txVariable* var = (txVariable*)mVariables.get(varName); + if (var) { + var->setValue(value); + + return NS_OK; + } + + var = new txVariable(value); + NS_ENSURE_TRUE(var, NS_ERROR_OUT_OF_MEMORY); + + return mVariables.add(varName, var); +} + PR_BEGIN_EXTERN_C void* PR_CALLBACK HandleTransformBlockerEvent(PLEvent *aEvent) diff --git a/mozilla/extensions/transformiix/source/xslt/txMozillaXSLTProcessor.h b/mozilla/extensions/transformiix/source/xslt/txMozillaXSLTProcessor.h index 4c1f3e309db..5d1e4fe519a 100644 --- a/mozilla/extensions/transformiix/source/xslt/txMozillaXSLTProcessor.h +++ b/mozilla/extensions/transformiix/source/xslt/txMozillaXSLTProcessor.h @@ -52,11 +52,13 @@ #include "nsVoidArray.h" #include "nsAutoPtr.h" #include "nsIDocumentObserver.h" +#include "txNamespaceMap.h" class nsIURI; class nsIXMLContentSink; class nsIDOMNode; class nsIPrincipal; +class txResultRecycler; /* bacd8ad0-552f-11d3-a9f7-000064657374 */ #define TRANSFORMIIX_XSLT_PROCESSOR_CID \ @@ -70,13 +72,17 @@ class nsIPrincipal; class txVariable : public txIGlobalParameter { public: - txVariable(nsIVariant *aValue) : mValue(aValue), - mTxValue(nsnull) + txVariable(nsIVariant *aValue) : mValue(aValue) { + NS_ASSERTION(aValue, "missing value"); + } + txVariable(txAExprResult* aValue) : mTxValue(aValue) + { + NS_ASSERTION(aValue, "missing value"); } nsresult getValue(txAExprResult** aValue) { - NS_ASSERTION(mValue, "variablevalue is null"); + NS_ASSERTION(mValue || mTxValue, "variablevalue is null"); if (!mTxValue) { nsresult rv = Convert(mValue, getter_AddRefs(mTxValue)); @@ -100,6 +106,12 @@ public: mValue = aValue; mTxValue = nsnull; } + void setValue(txAExprResult* aValue) + { + NS_ASSERTION(aValue, "setting variablevalue to null"); + mValue = nsnull; + mTxValue = aValue; + } private: static nsresult Convert(nsIVariant *aValue, txAExprResult** aResult); @@ -114,6 +126,7 @@ private: class txMozillaXSLTProcessor : public nsIXSLTProcessor, public nsIXSLTProcessorObsolete, public nsIDocumentTransformer, + public nsIDocumentTransformer_1_8_BRANCH, public nsIDocumentObserver { public: @@ -142,6 +155,13 @@ public: nsIPrincipal* aCallerPrincipal); NS_IMETHOD SetSourceContentModel(nsIDOMNode* aSource); NS_IMETHOD CancelLoads() {return NS_OK;}; + NS_IMETHOD AddXSLTParamNamespace(const nsString& aPrefix, + const nsString& aNamespace); + NS_IMETHOD AddXSLTParam(const nsString& aName, + const nsString& aNamespace, + const nsString& aSelect, + const nsString& aValue, + nsIDOMNode* aContext); // nsIDocumentObserver interface NS_DECL_NSIDOCUMENTOBSERVER @@ -173,6 +193,8 @@ private: nsString mErrorText, mSourceText; nsCOMPtr mObserver; txExpandedNameMap mVariables; + txNamespaceMap mParamNamespaceMap; + nsRefPtr mRecycler; }; extern nsresult TX_LoadSheet(nsIURI* aUri, txMozillaXSLTProcessor* aProcessor, diff --git a/mozilla/extensions/transformiix/source/xslt/txStylesheetCompiler.cpp b/mozilla/extensions/transformiix/source/xslt/txStylesheetCompiler.cpp index 262b9a7c14c..d02d87b1e09 100644 --- a/mozilla/extensions/transformiix/source/xslt/txStylesheetCompiler.cpp +++ b/mozilla/extensions/transformiix/source/xslt/txStylesheetCompiler.cpp @@ -129,11 +129,11 @@ txStylesheetCompiler::startElement(PRInt32 aNamespaceID, nsIAtom* aLocalName, } if (attr->mLocalName == txXMLAtoms::xmlns) { - mElementContext->mMappings->addNamespace(nsnull, attr->mValue); + mElementContext->mMappings->mapNamespace(nsnull, attr->mValue); } else { mElementContext->mMappings-> - addNamespace(attr->mLocalName, attr->mValue); + mapNamespace(attr->mLocalName, attr->mValue); } } } @@ -193,7 +193,7 @@ txStylesheetCompiler::startElement(const PRUnichar *aName, } rv = mElementContext->mMappings-> - addNamespace(prefixToBind, atts[i].mValue); + mapNamespace(prefixToBind, atts[i].mValue); NS_ENSURE_SUCCESS(rv, rv); } }