KHtml

path.cpp
1 /*
2  * path.cc - Copyright 2005 Frerich Raabe <[email protected]>
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 #include "path.h"
26 
27 #include "xml/dom_docimpl.h"
28 #include "xml/dom_nodeimpl.h"
29 
30 using namespace DOM;
31 using namespace khtml;
32 using namespace khtml::XPath;
33 
34 Filter::Filter(Expression *expr, const QList<Predicate *> &predicates)
35  : m_expr(expr),
36  m_predicates(predicates)
37 {
38 }
39 
40 Filter::~Filter()
41 {
42  delete m_expr;
43  qDeleteAll(m_predicates);
44 }
45 
46 QString Filter::dump() const
47 {
48  QString s = "<filter>";
49  s += m_expr->dump();
50  foreach (Predicate *predicate, m_predicates) {
51  s += predicate->dump();
52  }
53  s += "</filter>";
54  return s;
55 }
56 
57 Value Filter::doEvaluate() const
58 {
59  Value v = m_expr->evaluate();
60  if (!v.isNodeset()) {
61  if (!m_predicates.empty()) {
62  // qCDebug(KHTML_LOG) << "Ignoring predicates for filter since expression does not evaluate to a nodeset!";
63  }
64  return v;
65  }
66 
67  DomNodeList inNodes = v.toNodeset(), outNodes;
68 
69  // Filter seems to work in document order, not axis order
70  inNodes->normalizeUpto(StaticNodeListImpl::DocumentOrder);
71 
72  foreach (Predicate *predicate, m_predicates) {
73  outNodes = new StaticNodeListImpl();
74  Expression::evaluationContext().size = int(inNodes->length());
75 
76  for (unsigned long n = 0; n < inNodes->length(); ++n) {
77  NodeImpl *node = inNodes->item(n);
78  Expression::evaluationContext().node = node;
79  Expression::evaluationContext().position = n + 1;
80 
81  if (predicate->evaluate()) {
82  outNodes->append(node);
83  }
84  }
85 
86  inNodes = outNodes;
87  outNodes->setKnownNormalization(StaticNodeListImpl::DocumentOrder);
88 
89 #ifdef XPATH_VERBOSE
90  qCDebug(KHTML_LOG) << "Predicate within filter trims to:" << outNodes->length();
91 #endif
92  }
93 
94  return Value(outNodes);
95 }
96 
97 LocationPath::LocationPath()
98  : m_absolute(false)
99 {
100 }
101 
102 LocationPath::~LocationPath()
103 {
104  qDeleteAll(m_steps);
105 }
106 
107 void LocationPath::optimize()
108 {
109  foreach (Step *step, m_steps) {
110  step->optimize();
111  }
112 }
113 
114 Value LocationPath::doEvaluate() const
115 {
116 #ifdef XPATH_VERBOSE
117  if (m_absolute) {
118  qCDebug(KHTML_LOG) << "Evaluating absolute path expression, steps:" << m_steps.count();
119  } else {
120  qCDebug(KHTML_LOG) << "Evaluating relative path expression, steps:" << m_steps.count();
121  }
122 #endif
123 
124  DomNodeList inDomNodes = new StaticNodeListImpl,
125  outDomNodes;
126 
127  /* For absolute location paths, the context node is ignored - the
128  * document's root node is used instead.
129  */
130  NodeImpl *context = Expression::evaluationContext().node;
131  if (m_absolute) {
132  if (context->nodeType() != Node::DOCUMENT_NODE) {
133  context = context->ownerDocument();
134  }
135  }
136 
137  inDomNodes->append(context);
138 
139  if (m_steps.isEmpty()) {
140  return Value(inDomNodes);
141  }
142 
143  int s = 0;
144  foreach (Step *step, m_steps) {
145 #ifdef XPATH_VERBOSE
146  qCDebug(KHTML_LOG) << "-------------------------------------";
147  qCDebug(KHTML_LOG) << "Step " << s << "insize " << inDomNodes->length();
148 #endif
149 
150  outDomNodes = new StaticNodeListImpl;
151  for (unsigned long i = 0; i < inDomNodes->length(); ++i) {
152  DomNodeList matches = step->evaluate(inDomNodes->item(i));
153  for (unsigned long j = 0; j < matches->length(); ++j) {
154  outDomNodes->append(matches->item(j));
155  }
156  }
157  inDomNodes = outDomNodes;
158 
159  ++s;
160  }
161 
162 #ifdef XPATH_VERBOSE
163  qCDebug(KHTML_LOG) << "-------------------------------------";
164  qCDebug(KHTML_LOG) << "output:" << outDomNodes->length();
165  qCDebug(KHTML_LOG) << "=====================================";
166 #endif
167 
168  return Value(outDomNodes);
169 }
170 
171 QString LocationPath::dump() const
172 {
173  QString s = "<locationpath absolute=\"";
174  s += m_absolute ? "true" : "false";
175  s += "\">";
176  foreach (Step *step, m_steps) {
177  s += step->dump();
178  }
179  s += "</locationpath>";
180  return s;
181 }
182 
183 Path::Path(Filter *filter, LocationPath *path)
184  : m_filter(filter),
185  m_path(path)
186 {
187 }
188 
189 Path::~Path()
190 {
191  delete m_filter;
192  delete m_path;
193 }
194 
195 QString Path::dump() const
196 {
197  if (!m_filter && !m_path) {
198  return "<path/>";
199  }
200 
201  QString s = "<path>";
202  if (m_filter) {
203  s += m_filter->dump();
204  }
205  if (m_path) {
206  s += m_path->dump();
207  }
208  s += "</path>";
209 
210  return s;
211 }
212 
213 Value Path::doEvaluate() const
214 {
215  NodeImpl *saveCtx = Expression::evaluationContext().node;
216 
217  Value initial = m_filter->evaluate();
218  if (initial.isNodeset()) {
219  // Pass in every output from the filter to the path, and union the results
220  DomNodeList out = new StaticNodeListImpl();
221  DomNodeList in = initial.toNodeset();
222 
223  for (unsigned long i = 0; i < in->length(); ++i) {
224  Expression::evaluationContext().node = in->item(i);
225 
226  DomNodeList singleSet = m_path->evaluate().toNodeset();
227  for (unsigned long j = 0; j < singleSet->length(); ++ j) {
228  out->append(singleSet->item(j));
229  }
230  }
231 
232  Expression::evaluationContext().node = saveCtx;
233  return Value(out);
234  } else {
235  // ### what should happen in this case?
236  Expression::reportInvalidExpressionErr();
237  return Value();
238  }
239 }
240 
This file is part of the HTML rendering engine for KDE.
This library provides a full-featured HTML parser and widget.
int length() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Tue Oct 26 2021 22:48:06 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.