Commit 0315a98f authored by andersca's avatar andersca

WebCore:

2006-06-04  Anders Carlsson  <acarlsson@apple.com>

        Reviewed by Darin.

        http://bugzilla.opendarwin.org/show_bug.cgi?id=9035
        document.evaluate and createNSResolver miss on namespaced elements
        
        * xpath/XPathExpression.cpp:
        (WebCore::XPathExpression::createExpression):
        Pass the resolver to the parser.
        
        * xpath/XPathResult.cpp:
        (WebCore::XPathResult::iterateNext):
        Fix off-by-one error.
        
        * xpath/impl/XPathExpressionNode.h:
        (WebCore::XPath::EvaluationContext::EvaluationContext):
        Get rid of the resolver in the evaluation context.
        
        * xpath/impl/XPathGrammar.y:
        Fetch the resolver from the parser. Only return the local name.
        
        * xpath/impl/XPathParser.cpp:        
        (WebCore::XPath::Parser::parseStatement):
        * xpath/impl/XPathParser.h:
        (WebCore::XPath::Parser::resolver):
        Update to hold the resolver.
        
        * xpath/impl/XPathStep.cpp:
        (WebCore::XPath::Step::Step):
        If the parser has stored a namespace URI, set it.
        
        (WebCore::XPath::Step::nodeTestMatches):
        Check namespace URIs.
        
        * xpath/impl/XPathStep.h:
        Add m_namespaceURI.

LayoutTests:

2006-06-04  Anders Carlsson  <acarlsson@apple.com>

        Reviewed by Darin.

        http://bugzilla.opendarwin.org/show_bug.cgi?id=9035
        document.evaluate and createNSResolver miss on namespaced elements

        * fast/xpath: Added.
        * fast/xpath/xpath-namespaces-expected.txt: Added.
        * fast/xpath/xpath-namespaces.html: Added.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@14717 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent a0cd6749
2006-06-04 Anders Carlsson <acarlsson@apple.com>
Reviewed by Darin.
http://bugzilla.opendarwin.org/show_bug.cgi?id=9035
document.evaluate and createNSResolver miss on namespaced elements
* fast/xpath: Added.
* fast/xpath/xpath-namespaces-expected.txt: Added.
* fast/xpath/xpath-namespaces.html: Added.
2006-06-03 David Kilzer <ddkilzer@kilzer.net>
Reviewed by Eric.
This tests that XPath expressions with prefixes work correctly.
SUCCESS: test completed
<html>
<head>
<script>
function debug(str) {
var d = document.getElementById('console');
d.appendChild(document.createTextNode(str + "\n"));
}
function runTests () {
if (window.layoutTestController)
layoutTestController.dumpAsText();
var xmlString = '<ns:foo xmlns:ns="http://www.example.org">';
var doc = (new DOMParser()).parseFromString(xmlString, "text/xml");
var contextNode = doc.documentElement;
var nsResolver = document.createNSResolver(contextNode);
var expr = doc.createExpression("/ns:foo", nsResolver);
var result = expr.evaluate(contextNode, XPathResult.ANY_TYPE, null)
var element = result.iterateNext();
if (element == 0) {
debug('FAILURE: no result node was found');
return;
}
if (element.nodeName != 'ns:foo') {
debug('FAILURE: did not find the correct node');
return;
}
debug('SUCCESS: test completed')
}
</script>
</head>
<body onload="runTests()">
This tests that XPath expressions with prefixes work correctly.
<pre id="console">
</pre>
</body>
</html>
2006-06-04 Anders Carlsson <acarlsson@apple.com>
Reviewed by Darin.
http://bugzilla.opendarwin.org/show_bug.cgi?id=9035
document.evaluate and createNSResolver miss on namespaced elements
* xpath/XPathExpression.cpp:
(WebCore::XPathExpression::createExpression):
Pass the resolver to the parser.
* xpath/XPathResult.cpp:
(WebCore::XPathResult::iterateNext):
Fix off-by-one error.
* xpath/impl/XPathExpressionNode.h:
(WebCore::XPath::EvaluationContext::EvaluationContext):
Get rid of the resolver in the evaluation context.
* xpath/impl/XPathGrammar.y:
Fetch the resolver from the parser. Only return the local name.
* xpath/impl/XPathParser.cpp:
(WebCore::XPath::Parser::parseStatement):
* xpath/impl/XPathParser.h:
(WebCore::XPath::Parser::resolver):
Update to hold the resolver.
* xpath/impl/XPathStep.cpp:
(WebCore::XPath::Step::Step):
If the parser has stored a namespace URI, set it.
(WebCore::XPath::Step::nodeTestMatches):
Check namespace URIs.
* xpath/impl/XPathStep.h:
Add m_namespaceURI.
2006-06-03 Rob Buis <buis@kde.org>
Reviewed by mjs. Tweaked and landed by ddkilzer.
......
......@@ -1524,23 +1524,6 @@
FAE04190097596C9000540BE /* SVGImageLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = FAE0418E097596C9000540BE /* SVGImageLoader.h */; };
/* End PBXBuildFile section */
/* Begin PBXBuildStyle section */
AB2167DF0A2FA8B90058A52C /* Development */ = {
isa = PBXBuildStyle;
buildSettings = {
COPY_PHASE_STRIP = NO;
};
name = Development;
};
AB2167E00A2FA8B90058A52C /* Deployment */ = {
isa = PBXBuildStyle;
buildSettings = {
COPY_PHASE_STRIP = YES;
};
name = Deployment;
};
/* End PBXBuildStyle section */
/* Begin PBXContainerItemProxy section */
DD041FF009D9E3250010AF2A /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
......@@ -6233,12 +6216,6 @@
0867D690FE84028FC02AAC07 /* Project object */ = {
isa = PBXProject;
buildConfigurationList = 149C284308902B11008A9EFC /* Build configuration list for PBXProject "WebCore" */;
buildSettings = {
};
buildStyles = (
AB2167DF0A2FA8B90058A52C /* Development */,
AB2167E00A2FA8B90058A52C /* Deployment */,
);
hasScannedForEncodings = 1;
knownRegions = (
English,
......
......@@ -47,8 +47,7 @@ PassRefPtr<XPathExpression> XPathExpression::createExpression(const String& expr
RefPtr<XPathExpression> expr = new XPathExpression;
Parser parser;
Expression::evaluationContext().resolver = resolver;
expr->m_topExpression = parser.parseStatement(expression, ec);
expr->m_topExpression = parser.parseStatement(expression, resolver, ec);
if (!expr->m_topExpression)
return 0;
......
......@@ -206,7 +206,7 @@ Node* XPathResult::iterateNext(ExceptionCode& ec)
return 0;
}
if (m_nodeSetPosition + 1 >= m_nodeSet.size())
if (m_nodeSetPosition + 1 > m_nodeSet.size())
return 0;
Node* node = m_nodeSet[m_nodeSetPosition].get();
......
......@@ -29,6 +29,8 @@
#if XPATH_SUPPORT
#include "XPathNSResolver.h"
#include "StringHash.h"
#include <wtf/HashMap.h>
#include <wtf/Vector.h>
......@@ -36,14 +38,13 @@
namespace WebCore {
class Node;
class XPathNSResolver;
namespace XPath {
class Value;
struct EvaluationContext {
EvaluationContext() : node(0), size(0), position(0), resolver(0) { }
EvaluationContext() : node(0), size(0), position(0) { }
RefPtr<Node> node;
unsigned long size;
......@@ -53,7 +54,6 @@ struct EvaluationContext {
/* The function library is globally accessible through
* FunctionLibrary::self()
*/
XPathNSResolver* resolver;
};
class ParseNode {
......
......@@ -223,11 +223,23 @@ NodeTest:
const int colon = $1->find(':');
if (colon > -1) {
String prefix($1->left(colon));
XPathNSResolver *resolver = Expression::evaluationContext().resolver;
if (!resolver || resolver->lookupNamespaceURI(prefix).isNull()) {
XPathNSResolver *resolver = static_cast<Parser*>(parser)->resolver();
if (!resolver) {
static_cast<Parser*>(parser)->m_gotNamespaceError = true;
YYABORT;
}
static_cast<Parser*>(parser)->m_currentNamespaceURI = resolver->lookupNamespaceURI(prefix);
if (static_cast<Parser*>(parser)->m_currentNamespaceURI.isNull()) {
static_cast<Parser*>(parser)->m_gotNamespaceError = true;
YYABORT;
}
$$ = new String($1->substring(colon + 1));
delete $1;
static_cast<Parser*>(parser)->registerString($$);
static_cast<Parser*>(parser)->unregisterString($1);
}
}
|
......
......@@ -430,10 +430,12 @@ int Parser::lex(void* data)
return tok.type;
}
Expression* Parser::parseStatement(const String& statement, ExceptionCode& ec)
Expression* Parser::parseStatement(const String& statement, PassRefPtr<XPathNSResolver> resolver, ExceptionCode& ec)
{
reset(statement);
m_resolver = resolver;
Parser* oldParser = currentParser;
currentParser = this;
int parseError = xpathyyparse(this);
......
......@@ -41,6 +41,9 @@
#include "XPathUtil.h"
namespace WebCore {
class XPathResolver;
namespace XPath {
struct Token {
......@@ -61,6 +64,7 @@ private:
unsigned m_nextPos;
String m_data;
int m_lastTokenType;
RefPtr<XPathNSResolver> m_resolver;
static HashMap<String, Step::AxisType>* s_axisNamesDict;
static HashSet<String>* s_nodeTypeNamesDict;
......@@ -101,7 +105,8 @@ private:
public:
Parser();
Expression* parseStatement(const String& statement, ExceptionCode&);
XPathNSResolver* resolver() const { return m_resolver.get(); }
Expression* parseStatement(const String& statement, PassRefPtr<XPathNSResolver>, ExceptionCode&);
static Parser* current() { return currentParser; }
......@@ -109,6 +114,7 @@ public:
Expression* m_topExpr;
bool m_gotNamespaceError;
String m_currentNamespaceURI;
void registerParseNode(ParseNode*);
void unregisterParseNode(ParseNode*);
......
......@@ -34,6 +34,7 @@
#include "Node.h"
#include "Text.h"
#include "XPathNSResolver.h"
#include "XPathParser.h"
namespace WebCore {
namespace XPath {
......@@ -63,10 +64,15 @@ Step::Step()
}
Step::Step(AxisType axis, const String& nodeTest, const Vector<Predicate*>& predicates)
: m_axis(axis),
m_nodeTest(nodeTest),
m_predicates(predicates)
: m_axis(axis)
, m_nodeTest(nodeTest)
, m_predicates(predicates)
{
Parser* parser = Parser::current();
ASSERT(parser);
m_namespaceURI = parser->m_currentNamespaceURI;
parser->m_currentNamespaceURI = String();
}
Step::~Step()
......@@ -213,17 +219,14 @@ NodeVector Step::nodesInAxis(Node* context) const
NodeVector Step::nodeTestMatches(const NodeVector& nodes) const
{
String ns = namespaceFromNodetest(m_nodeTest);
NodeVector matches;
if (m_nodeTest == "*") {
for (unsigned i = 0; i < nodes.size(); i++) {
Node* node = nodes[i].get();
if (node->nodeType() == primaryNodeType(m_axis)) {
if (ns.isEmpty() ||
node->namespaceURI() == ns) {
matches.append(node);
}
}
if (node->nodeType() == primaryNodeType(m_axis) &&
(m_namespaceURI.isEmpty() || m_namespaceURI == node->namespaceURI()))
matches.append(node);
}
return nodes;
} else if (m_nodeTest == "text()") {
......@@ -259,31 +262,16 @@ NodeVector Step::nodeTestMatches(const NodeVector& nodes) const
} else if (m_nodeTest == "node()")
return nodes;
else {
String prefix, localName;
const int colon = m_nodeTest.find(':');
if (colon > -1) {
prefix = m_nodeTest.left(colon);
localName = m_nodeTest.deprecatedString().mid(colon + 1);
} else {
localName = m_nodeTest;
}
if (!prefix.isEmpty() &&
Expression::evaluationContext().resolver->lookupNamespaceURI(prefix).isEmpty()) {
/* FIXME: Throw NAMESPACE_ERR exception */
}
if (m_axis == AttributeAxis) {
// In XPath land, namespace nodes are not accessible
// on the attribute axis.
if (localName == "xmlns")
if (m_nodeTest == "xmlns")
return matches;
for (unsigned i = 0; i < nodes.size(); i++) {
Node* node = nodes[i].get();
if (node->nodeName() == localName) {
if (node->nodeName() == m_nodeTest) {
matches.append(node);
break; // There can only be one.
}
......@@ -295,13 +283,13 @@ NodeVector Step::nodeTestMatches(const NodeVector& nodes) const
} else {
for (unsigned i = 0; i < nodes.size(); i++) {
Node* node = nodes[i].get();
// We use tagQName here because we don't want the element name in uppercase
// like we get with HTML elements.
if (node->nodeType() == Node::ELEMENT_NODE &&
static_cast<Element*>(node)->tagQName().toString() == localName) {
static_cast<Element*>(node)->tagQName().localName() == m_nodeTest &&
(m_namespaceURI.isNull() || m_namespaceURI == node->namespaceURI()))
matches.append(node);
}
}
return matches;
......@@ -317,18 +305,6 @@ void Step::optimize()
m_predicates[i]->optimize();
}
String Step::namespaceFromNodetest(const String& nodeTest) const
{
int i = nodeTest.find(':');
if (i == -1)
return String();
String prefix(nodeTest.left(i));
Node* ctxNode = Expression::evaluationContext().node.get();
return ctxNode->lookupNamespaceURI(prefix);
}
Node::NodeType Step::primaryNodeType(AxisType axis) const
{
switch (axis) {
......
......@@ -65,6 +65,7 @@ private:
AxisType m_axis;
String m_nodeTest;
String m_namespaceURI;
Vector<Predicate*> m_predicates;
};
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment