From 37c5c969e93e67e880adb7028131438a80925f9b Mon Sep 17 00:00:00 2001 From: "sicking%bigfoot.com" Date: Fri, 14 Feb 2003 00:59:40 +0000 Subject: [PATCH] Bug 174713: Make XPath on HTML documents behave consistently and HTML-ish. This makes the XPath-functions name() and local-name() return upper-case names and makes nametests case-insensitive. r=peterv sr=jst a=asa git-svn-id: svn://10.0.0.236/trunk@137794 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/content/base/public/MANIFEST | 1 + mozilla/content/base/public/Makefile.in | 1 + .../base/public/nsIXPathEvaluatorInternal.h | 62 +++++++++++++++++++ mozilla/content/base/src/nsDocument.cpp | 8 +++ .../transformiix/source/xpath/ExprParser.cpp | 15 ++++- .../transformiix/source/xpath/ExprParser.h | 3 +- .../transformiix/source/xpath/Makefile.in | 1 + .../source/xpath/NodeSetFunctionCall.cpp | 14 +++++ .../source/xpath/nsXPathEvaluator.cpp | 18 +++++- .../source/xpath/nsXPathEvaluator.h | 16 ++++- .../source/xpath/txIXPathContext.h | 5 ++ .../source/xslt/ProcessorState.cpp | 5 ++ .../transformiix/source/xslt/ProcessorState.h | 1 + .../source/xslt/txPatternParser.cpp | 3 +- 14 files changed, 144 insertions(+), 9 deletions(-) create mode 100644 mozilla/content/base/public/nsIXPathEvaluatorInternal.h diff --git a/mozilla/content/base/public/MANIFEST b/mozilla/content/base/public/MANIFEST index a0834550cae..1c2f80669b9 100644 --- a/mozilla/content/base/public/MANIFEST +++ b/mozilla/content/base/public/MANIFEST @@ -30,5 +30,6 @@ nsIStyleSheetLinkingElement.h nsITextContent.h nsIContentList.h nsIFrameLoader.h +nsIXPathEvaluatorInternal.h mozISanitizingSerializer.h nsContentCID.h diff --git a/mozilla/content/base/public/Makefile.in b/mozilla/content/base/public/Makefile.in index 3a3b96af61c..1ae072fa1d6 100644 --- a/mozilla/content/base/public/Makefile.in +++ b/mozilla/content/base/public/Makefile.in @@ -58,6 +58,7 @@ nsITextContent.h \ nsIPrivateDOMImplementation.h \ nsIContentSerializer.h \ nsIHTMLToTextSink.h \ +nsIXPathEvaluatorInternal.h \ mozISanitizingSerializer.h \ nsIContentList.h \ nsIFrameLoader.h \ diff --git a/mozilla/content/base/public/nsIXPathEvaluatorInternal.h b/mozilla/content/base/public/nsIXPathEvaluatorInternal.h new file mode 100644 index 00000000000..39117cc5be8 --- /dev/null +++ b/mozilla/content/base/public/nsIXPathEvaluatorInternal.h @@ -0,0 +1,62 @@ +/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Jonas Sicking (Original author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsIXPathEvaluatorInternal_h__ +#define nsIXPathEvaluatorInternal_h__ + +#include "nsISupports.h" + +class nsIDOMDocument; + +#define NS_IXPATHEVALUATORINTERNAL_IID \ + {0xb4b72daa, 0x65d6, 0x440f, \ + { 0xb6, 0x08, 0xe2, 0xee, 0x9a, 0x82, 0xf3, 0x13 }} + +class nsIXPathEvaluatorInternal : public nsISupports +{ +public: + + NS_DEFINE_STATIC_IID_ACCESSOR(NS_IXPATHEVALUATORINTERNAL_IID) + + /** + * Sets the document this evaluator corresponds to + */ + NS_IMETHOD SetDocument(nsIDOMDocument* aDocument) = 0; +}; + +#endif //nsIXPathEvaluatorInternal_h__ diff --git a/mozilla/content/base/src/nsDocument.cpp b/mozilla/content/base/src/nsDocument.cpp index 743d14ec495..41c334797e8 100644 --- a/mozilla/content/base/src/nsDocument.cpp +++ b/mozilla/content/base/src/nsDocument.cpp @@ -148,6 +148,7 @@ static NS_DEFINE_CID(kDOMEventGroupCID, NS_DOMEVENTGROUP_CID); #include "nsIPrefService.h" #include "nsScriptEventManager.h" +#include "nsIXPathEvaluatorInternal.h" /** * A struct that holds all the information about a radio group. @@ -654,6 +655,13 @@ NS_INTERFACE_MAP_BEGIN(nsDocument) return NS_ERROR_NO_INTERFACE; } NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr internal = + do_QueryInterface(evaluator); + if (internal) { + internal->SetDocument(this); + } + mXPathDocument = new nsXPathDocumentTearoff(evaluator, this); NS_ENSURE_TRUE(mXPathDocument, NS_ERROR_OUT_OF_MEMORY); } diff --git a/mozilla/extensions/transformiix/source/xpath/ExprParser.cpp b/mozilla/extensions/transformiix/source/xpath/ExprParser.cpp index 82c6ce65da6..c6740e36761 100644 --- a/mozilla/extensions/transformiix/source/xpath/ExprParser.cpp +++ b/mozilla/extensions/transformiix/source/xpath/ExprParser.cpp @@ -643,7 +643,8 @@ LocationStep* ExprParser::createLocationStep(ExprLexer& lexer, nsresult rv = resolveQName(tok->value, getter_AddRefs(prefix), aContext, - getter_AddRefs(lName), nspace); + getter_AddRefs(lName), nspace, + PR_TRUE); if (NS_FAILED(rv)) { // XXX error report namespace resolve failed return 0; @@ -1012,7 +1013,8 @@ short ExprParser::precedenceLevel(short tokenType) { nsresult ExprParser::resolveQName(const nsAString& aQName, nsIAtom** aPrefix, txIParseContext* aContext, - nsIAtom** aLocalName, PRInt32& aNamespace) + nsIAtom** aLocalName, PRInt32& aNamespace, + PRBool aIsNameTest) { aNamespace = kNameSpaceID_None; PRInt32 idx = aQName.FindChar(':'); @@ -1031,7 +1033,14 @@ nsresult ExprParser::resolveQName(const nsAString& aQName, } // the lexer dealt with idx == 0 *aPrefix = 0; - *aLocalName = NS_NewAtom(aQName); + if (aIsNameTest && aContext->caseInsensitiveNameTests()) { + nsAutoString lcname; + TX_ToLowerCase(aQName, lcname); + *aLocalName = NS_NewAtom(lcname); + } + else { + *aLocalName = NS_NewAtom(aQName); + } if (!*aLocalName) { return NS_ERROR_OUT_OF_MEMORY; } diff --git a/mozilla/extensions/transformiix/source/xpath/ExprParser.h b/mozilla/extensions/transformiix/source/xpath/ExprParser.h index 8ca848ca082..f92a8634613 100644 --- a/mozilla/extensions/transformiix/source/xpath/ExprParser.h +++ b/mozilla/extensions/transformiix/source/xpath/ExprParser.h @@ -84,7 +84,8 @@ protected: **/ static nsresult resolveQName(const nsAString& aQName, nsIAtom** aPrefix, txIParseContext* aContext, - nsIAtom** aLocalName, PRInt32& aNamespace); + nsIAtom** aLocalName, PRInt32& aNamespace, + PRBool aIsNameTest = MB_FALSE); /** * Using the given lexer, parses the tokens if they represent a diff --git a/mozilla/extensions/transformiix/source/xpath/Makefile.in b/mozilla/extensions/transformiix/source/xpath/Makefile.in index d4512671de4..5b0bff14d94 100644 --- a/mozilla/extensions/transformiix/source/xpath/Makefile.in +++ b/mozilla/extensions/transformiix/source/xpath/Makefile.in @@ -38,6 +38,7 @@ REQUIRES += dom \ xpconnect \ js \ unicharutil \ + layout \ $(NULL) endif diff --git a/mozilla/extensions/transformiix/source/xpath/NodeSetFunctionCall.cpp b/mozilla/extensions/transformiix/source/xpath/NodeSetFunctionCall.cpp index 596c45c30ac..5a933247483 100644 --- a/mozilla/extensions/transformiix/source/xpath/NodeSetFunctionCall.cpp +++ b/mozilla/extensions/transformiix/source/xpath/NodeSetFunctionCall.cpp @@ -38,6 +38,9 @@ #include "txIXPathContext.h" #include "txTokenizer.h" #include "XMLDOMUtils.h" +#ifndef TX_EXE +#include "nsIDOMNode.h" +#endif /* * Creates a NodeSetFunctionCall of the given type @@ -161,12 +164,23 @@ ExprResult* NodeSetFunctionCall::evaluate(txIEvalContext* aContext) { case LOCAL_NAME: { nsAutoString localName; +#ifdef TX_EXE nsCOMPtr localNameAtom; node->getLocalName(getter_AddRefs(localNameAtom)); if (localNameAtom) { // Node has a localName localNameAtom->ToString(localName); } +#else + // The mozilla HTML-elements returns different casing for + // the localName-atom and .localName. Once we have a + // treeWalker it should have a getLocalName(nsAString&) + // function. + nsCOMPtr mozNode = + do_QueryInterface(node->getNSObj()); + NS_ASSERTION(mozNode, "wrapper doesn't wrap a nsIDOMNode"); + mozNode->GetLocalName(localName); +#endif return new StringResult(localName); } diff --git a/mozilla/extensions/transformiix/source/xpath/nsXPathEvaluator.cpp b/mozilla/extensions/transformiix/source/xpath/nsXPathEvaluator.cpp index 4c9d31025c5..7cc206b79df 100644 --- a/mozilla/extensions/transformiix/source/xpath/nsXPathEvaluator.cpp +++ b/mozilla/extensions/transformiix/source/xpath/nsXPathEvaluator.cpp @@ -49,6 +49,7 @@ #include "ExprParser.h" #include "nsDOMError.h" #include "txURIUtils.h" +#include "nsIHTMLDocument.h" extern nsINameSpaceManager* gTxNameSpaceManager; @@ -56,6 +57,7 @@ NS_IMPL_ADDREF(nsXPathEvaluator) NS_IMPL_RELEASE(nsXPathEvaluator) NS_INTERFACE_MAP_BEGIN(nsXPathEvaluator) NS_INTERFACE_MAP_ENTRY(nsIDOMXPathEvaluator) + NS_INTERFACE_MAP_ENTRY(nsIXPathEvaluatorInternal) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMXPathEvaluator) NS_INTERFACE_MAP_ENTRY_EXTERNAL_DOM_CLASSINFO(XPathEvaluator) NS_INTERFACE_MAP_END @@ -73,7 +75,8 @@ nsXPathEvaluator::CreateExpression(const nsAString & aExpression, nsIDOMXPathNSResolver *aResolver, nsIDOMXPathExpression **aResult) { - ParseContextImpl pContext(aResolver); + nsCOMPtr html = do_QueryInterface(mDocument); + ParseContextImpl pContext(aResolver, !!html); Expr* expression = ExprParser::createExpr(PromiseFlatString(aExpression), &pContext); if (!expression) @@ -123,6 +126,14 @@ nsXPathEvaluator::Evaluate(const nsAString & aExpression, return expression->Evaluate(aContextNode, aType, aInResult, aResult); } + +NS_IMETHODIMP +nsXPathEvaluator::SetDocument(nsIDOMDocument* aDocument) +{ + mDocument = aDocument; + return NS_OK; +} + /* * Implementation of txIParseContext private to nsXPathEvaluator * ParseContextImpl bases on a nsIDOMXPathNSResolver @@ -162,6 +173,11 @@ nsresult nsXPathEvaluator::ParseContextImpl::resolveFunctionCall(nsIAtom* aName, return NS_ERROR_XPATH_PARSE_FAILED; } +PRBool nsXPathEvaluator::ParseContextImpl::caseInsensitiveNameTests() +{ + return mIsHTML; +} + void nsXPathEvaluator::ParseContextImpl::receiveError(const nsAString& aMsg, nsresult aRes) { diff --git a/mozilla/extensions/transformiix/source/xpath/nsXPathEvaluator.h b/mozilla/extensions/transformiix/source/xpath/nsXPathEvaluator.h index 682ab0d4d35..dff7a76cc9e 100644 --- a/mozilla/extensions/transformiix/source/xpath/nsXPathEvaluator.h +++ b/mozilla/extensions/transformiix/source/xpath/nsXPathEvaluator.h @@ -42,11 +42,14 @@ #include "nsIDOMXPathEvaluator.h" #include "txIXPathContext.h" +#include "nsIXPathEvaluatorInternal.h" +#include "nsIDOMDocument.h" /** * A class for evaluating an XPath expression string */ -class nsXPathEvaluator : public nsIDOMXPathEvaluator +class nsXPathEvaluator : public nsIDOMXPathEvaluator, + public nsIXPathEvaluatorInternal { public: nsXPathEvaluator(); @@ -58,13 +61,16 @@ public: // nsIDOMXPathEvaluator interface NS_DECL_NSIDOMXPATHEVALUATOR + // nsIXPathEvaluatorInternal interface + NS_IMETHOD SetDocument(nsIDOMDocument* aDocument); + private: // txIParseContext implementation class ParseContextImpl : public txIParseContext { public: - ParseContextImpl(nsIDOMXPathNSResolver* aResolver) - : mResolver(aResolver), mLastError(NS_OK) + ParseContextImpl(nsIDOMXPathNSResolver* aResolver, PRBool aIsHTML) + : mResolver(aResolver), mLastError(NS_OK), mIsHTML(aIsHTML) { } @@ -80,12 +86,16 @@ private: nsresult resolveNamespacePrefix(nsIAtom* aPrefix, PRInt32& aID); nsresult resolveFunctionCall(nsIAtom* aName, PRInt32 aID, FunctionCall*& aFunction); + PRBool caseInsensitiveNameTests(); void receiveError(const nsAString& aMsg, nsresult aRes); private: nsIDOMXPathNSResolver* mResolver; nsresult mLastError; + PRBool mIsHTML; }; + + nsCOMPtr mDocument; }; /* d0a75e02-b5e7-11d5-a7f2-df109fb8a1fc */ diff --git a/mozilla/extensions/transformiix/source/xpath/txIXPathContext.h b/mozilla/extensions/transformiix/source/xpath/txIXPathContext.h index 4e73cecf6f5..f2cff9ffd22 100644 --- a/mozilla/extensions/transformiix/source/xpath/txIXPathContext.h +++ b/mozilla/extensions/transformiix/source/xpath/txIXPathContext.h @@ -75,6 +75,11 @@ public: virtual nsresult resolveFunctionCall(nsIAtom* aName, PRInt32 aID, FunctionCall*& aFunction) = 0; + /** + * Should nametests parsed in this context be case-sensitive + */ + virtual PRBool caseInsensitiveNameTests() = 0; + /* * Callback to be used by the Parser if errors are detected. */ diff --git a/mozilla/extensions/transformiix/source/xslt/ProcessorState.cpp b/mozilla/extensions/transformiix/source/xslt/ProcessorState.cpp index 81c5075986f..7bc14599894 100644 --- a/mozilla/extensions/transformiix/source/xslt/ProcessorState.cpp +++ b/mozilla/extensions/transformiix/source/xslt/ProcessorState.cpp @@ -1270,6 +1270,11 @@ nsresult txPSParseContext::resolveFunctionCall(nsIAtom* aName, PRInt32 aID, return mPS->resolveFunctionCall(aName, aID, mStyle, aFunction); } +PRBool txPSParseContext::caseInsensitiveNameTests() +{ + return PR_FALSE; +} + void txPSParseContext::receiveError(const nsAString& aMsg, nsresult aRes) { mPS->receiveError(aMsg, aRes); diff --git a/mozilla/extensions/transformiix/source/xslt/ProcessorState.h b/mozilla/extensions/transformiix/source/xslt/ProcessorState.h index 2682cddb229..ccfc2d68091 100644 --- a/mozilla/extensions/transformiix/source/xslt/ProcessorState.h +++ b/mozilla/extensions/transformiix/source/xslt/ProcessorState.h @@ -553,6 +553,7 @@ public: nsresult resolveNamespacePrefix(nsIAtom* aPrefix, PRInt32& aID); nsresult resolveFunctionCall(nsIAtom* aName, PRInt32 aID, FunctionCall*& aFunction); + PRBool caseInsensitiveNameTests(); void receiveError(const nsAString& aMsg, nsresult aRes); protected: diff --git a/mozilla/extensions/transformiix/source/xslt/txPatternParser.cpp b/mozilla/extensions/transformiix/source/xslt/txPatternParser.cpp index da3d1b78ffe..a606d31e476 100644 --- a/mozilla/extensions/transformiix/source/xslt/txPatternParser.cpp +++ b/mozilla/extensions/transformiix/source/xslt/txPatternParser.cpp @@ -41,6 +41,7 @@ #include "txAtoms.h" #include "txStringUtils.h" #include "txXSLTPatterns.h" +#include "txIXPathContext.h" txPattern* txPatternParser::createPattern(const nsAFlatString& aPattern, txIParseContext* aContext, @@ -304,7 +305,7 @@ nsresult txPatternParser::createStepPattern(ExprLexer& aLexer, nsCOMPtr prefix, lName; PRInt32 nspace; rv = resolveQName(tok->value, getter_AddRefs(prefix), aContext, - getter_AddRefs(lName), nspace); + getter_AddRefs(lName), nspace, PR_TRUE); if (NS_FAILED(rv)) { // XXX error report namespace resolve failed return rv;