Warning, file /frameworks/khtml/src/xpath/path.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 * path.cc - Copyright 2005 Frerich Raabe <raabe@kde.org> 0003 * 0004 * Redistribution and use in source and binary forms, with or without 0005 * modification, are permitted provided that the following conditions 0006 * are met: 0007 * 0008 * 1. Redistributions of source code must retain the above copyright 0009 * notice, this list of conditions and the following disclaimer. 0010 * 2. Redistributions in binary form must reproduce the above copyright 0011 * notice, this list of conditions and the following disclaimer in the 0012 * documentation and/or other materials provided with the distribution. 0013 * 0014 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 0015 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 0016 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 0017 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 0018 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 0019 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 0020 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 0021 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 0022 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 0023 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 0024 */ 0025 #include "path.h" 0026 0027 #include "xml/dom_docimpl.h" 0028 #include "xml/dom_nodeimpl.h" 0029 0030 using namespace DOM; 0031 using namespace khtml; 0032 using namespace khtml::XPath; 0033 0034 Filter::Filter(Expression *expr, const QList<Predicate *> &predicates) 0035 : m_expr(expr), 0036 m_predicates(predicates) 0037 { 0038 } 0039 0040 Filter::~Filter() 0041 { 0042 delete m_expr; 0043 qDeleteAll(m_predicates); 0044 } 0045 0046 QString Filter::dump() const 0047 { 0048 QString s = "<filter>"; 0049 s += m_expr->dump(); 0050 foreach (Predicate *predicate, m_predicates) { 0051 s += predicate->dump(); 0052 } 0053 s += "</filter>"; 0054 return s; 0055 } 0056 0057 Value Filter::doEvaluate() const 0058 { 0059 Value v = m_expr->evaluate(); 0060 if (!v.isNodeset()) { 0061 if (!m_predicates.empty()) { 0062 // qCDebug(KHTML_LOG) << "Ignoring predicates for filter since expression does not evaluate to a nodeset!"; 0063 } 0064 return v; 0065 } 0066 0067 DomNodeList inNodes = v.toNodeset(), outNodes; 0068 0069 // Filter seems to work in document order, not axis order 0070 inNodes->normalizeUpto(StaticNodeListImpl::DocumentOrder); 0071 0072 foreach (Predicate *predicate, m_predicates) { 0073 outNodes = new StaticNodeListImpl(); 0074 Expression::evaluationContext().size = int(inNodes->length()); 0075 0076 for (unsigned long n = 0; n < inNodes->length(); ++n) { 0077 NodeImpl *node = inNodes->item(n); 0078 Expression::evaluationContext().node = node; 0079 Expression::evaluationContext().position = n + 1; 0080 0081 if (predicate->evaluate()) { 0082 outNodes->append(node); 0083 } 0084 } 0085 0086 inNodes = outNodes; 0087 outNodes->setKnownNormalization(StaticNodeListImpl::DocumentOrder); 0088 0089 #ifdef XPATH_VERBOSE 0090 qCDebug(KHTML_LOG) << "Predicate within filter trims to:" << outNodes->length(); 0091 #endif 0092 } 0093 0094 return Value(outNodes); 0095 } 0096 0097 LocationPath::LocationPath() 0098 : m_absolute(false) 0099 { 0100 } 0101 0102 LocationPath::~LocationPath() 0103 { 0104 qDeleteAll(m_steps); 0105 } 0106 0107 void LocationPath::optimize() 0108 { 0109 foreach (Step *step, m_steps) { 0110 step->optimize(); 0111 } 0112 } 0113 0114 Value LocationPath::doEvaluate() const 0115 { 0116 #ifdef XPATH_VERBOSE 0117 if (m_absolute) { 0118 qCDebug(KHTML_LOG) << "Evaluating absolute path expression, steps:" << m_steps.count(); 0119 } else { 0120 qCDebug(KHTML_LOG) << "Evaluating relative path expression, steps:" << m_steps.count(); 0121 } 0122 #endif 0123 0124 DomNodeList inDomNodes = new StaticNodeListImpl, 0125 outDomNodes; 0126 0127 /* For absolute location paths, the context node is ignored - the 0128 * document's root node is used instead. 0129 */ 0130 NodeImpl *context = Expression::evaluationContext().node; 0131 if (m_absolute) { 0132 if (context->nodeType() != Node::DOCUMENT_NODE) { 0133 context = context->ownerDocument(); 0134 } 0135 } 0136 0137 inDomNodes->append(context); 0138 0139 if (m_steps.isEmpty()) { 0140 return Value(inDomNodes); 0141 } 0142 0143 int s = 0; 0144 foreach (Step *step, m_steps) { 0145 #ifdef XPATH_VERBOSE 0146 qCDebug(KHTML_LOG) << "-------------------------------------"; 0147 qCDebug(KHTML_LOG) << "Step " << s << "insize " << inDomNodes->length(); 0148 #endif 0149 0150 outDomNodes = new StaticNodeListImpl; 0151 for (unsigned long i = 0; i < inDomNodes->length(); ++i) { 0152 DomNodeList matches = step->evaluate(inDomNodes->item(i)); 0153 for (unsigned long j = 0; j < matches->length(); ++j) { 0154 outDomNodes->append(matches->item(j)); 0155 } 0156 } 0157 inDomNodes = outDomNodes; 0158 0159 ++s; 0160 } 0161 0162 #ifdef XPATH_VERBOSE 0163 qCDebug(KHTML_LOG) << "-------------------------------------"; 0164 qCDebug(KHTML_LOG) << "output:" << outDomNodes->length(); 0165 qCDebug(KHTML_LOG) << "====================================="; 0166 #endif 0167 0168 return Value(outDomNodes); 0169 } 0170 0171 QString LocationPath::dump() const 0172 { 0173 QString s = "<locationpath absolute=\""; 0174 s += m_absolute ? "true" : "false"; 0175 s += "\">"; 0176 foreach (Step *step, m_steps) { 0177 s += step->dump(); 0178 } 0179 s += "</locationpath>"; 0180 return s; 0181 } 0182 0183 Path::Path(Filter *filter, LocationPath *path) 0184 : m_filter(filter), 0185 m_path(path) 0186 { 0187 } 0188 0189 Path::~Path() 0190 { 0191 delete m_filter; 0192 delete m_path; 0193 } 0194 0195 QString Path::dump() const 0196 { 0197 if (!m_filter && !m_path) { 0198 return "<path/>"; 0199 } 0200 0201 QString s = "<path>"; 0202 if (m_filter) { 0203 s += m_filter->dump(); 0204 } 0205 if (m_path) { 0206 s += m_path->dump(); 0207 } 0208 s += "</path>"; 0209 0210 return s; 0211 } 0212 0213 Value Path::doEvaluate() const 0214 { 0215 NodeImpl *saveCtx = Expression::evaluationContext().node; 0216 0217 Value initial = m_filter->evaluate(); 0218 if (initial.isNodeset()) { 0219 // Pass in every output from the filter to the path, and union the results 0220 DomNodeList out = new StaticNodeListImpl(); 0221 DomNodeList in = initial.toNodeset(); 0222 0223 for (unsigned long i = 0; i < in->length(); ++i) { 0224 Expression::evaluationContext().node = in->item(i); 0225 0226 DomNodeList singleSet = m_path->evaluate().toNodeset(); 0227 for (unsigned long j = 0; j < singleSet->length(); ++ j) { 0228 out->append(singleSet->item(j)); 0229 } 0230 } 0231 0232 Expression::evaluationContext().node = saveCtx; 0233 return Value(out); 0234 } else { 0235 // ### what should happen in this case? 0236 Expression::reportInvalidExpressionErr(); 0237 return Value(); 0238 } 0239 } 0240