29 #include "xml/dom_docimpl.h"
30 #include "xml/dom_nodeimpl.h"
31 #include "xml/dom_textimpl.h"
32 #include "xml/dom3_xpathimpl.h"
39 using namespace DOM::XPath;
40 using namespace khtml;
41 using namespace khtml::XPath;
59 #warning "Might need more generic adjacency -- check"
62 return ( n->nextSibling() && ( n->nextSibling() == m ) ) ||
63 ( m->nextSibling() && ( m->nextSibling() == n ) );
70 for (
unsigned long n = 0; n < nodes->length(); ++n) {
71 NodeImpl* node = nodes->item( n );
72 NodeImpl*
next = n+1 < nodes->length() ? nodes->item( n+1 ) : 0;
75 outNodes->append( node );
77 QString s = node->nodeValue().string();
80 unsigned long n2 = n+1;
82 s += nodes->item( n2 )->nodeValue().string();
85 outNodes->append( node->document()->createTextNode(
new DOMStringImpl( s.data(), s.length() ) ) );
94 case AncestorAxis:
return "ancestor";
95 case AncestorOrSelfAxis:
return "ancestor-or-self";
96 case AttributeAxis:
return "attribute";
97 case ChildAxis:
return "child";
98 case DescendantAxis:
return "descendant";
99 case DescendantOrSelfAxis:
return "descendant-or-self";
100 case FollowingAxis:
return "following";
101 case FollowingSiblingAxis:
return "following-sibling";
102 case NamespaceAxis:
return "namespace";
103 case ParentAxis:
return "parent";
104 case PrecedingAxis:
return "preceding";
105 case PrecedingSiblingAxis:
return "preceding-sibling";
106 case SelfAxis:
return "self";
111 Step::Step(): m_compileState( NotCompiled )
118 m_nodeTest( nodeTest ),
119 m_compileState( NotCompiled ),
120 m_predicates( predicates )
126 qDeleteAll( m_predicates );
134 <<
", nodetest='" << m_nodeTest <<
"'"
135 <<
", " << m_predicates.count() <<
" predicates";
136 kDebug(6011) << DOM::getPrintableName( context->id() );
139 DomNodeList inNodes = nodesInAxis( context ), outNodes;
142 StaticNodeListImpl::NormalizationKind known = StaticNodeListImpl::AxisOrder;
143 inNodes->setKnownNormalization(known);
146 kDebug(6011) <<
"Axis " <<
axisAsString( m_axis ) <<
" matches " << inNodes->length() <<
" nodes.";
149 inNodes = nodeTestMatches( context, inNodes );
150 inNodes->setKnownNormalization(known);
153 kDebug(6011) <<
"\tNodetest " << m_nodeTest <<
" trims this number to " << inNodes->
length();
156 if ( m_predicates.isEmpty() )
159 foreach(
Predicate *predicate, m_predicates ) {
160 outNodes =
new StaticNodeListImpl;
164 for (
unsigned long n = 0; n < inNodes->length(); ++n ) {
165 NodeImpl* node = inNodes->item( n );
172 outNodes->append( node );
178 kDebug(6011) <<
"\tPredicate trims this number to " << outNodes->length();
181 inNodes->setKnownNormalization(known);
187 DomNodeList Step::nodesInAxis( NodeImpl *context )
const
196 n = n->nextSibling();
220 if ( context->nodeType() == Node::ATTRIBUTE_NODE ||
221 context->nodeType() == Node::XPATH_NAMESPACE_NODE ) {
225 NodeImpl *n = context->nextSibling();
228 n = n->nextSibling();
233 if ( context->nodeType() == Node::ATTRIBUTE_NODE ||
234 context->nodeType() == Node::XPATH_NAMESPACE_NODE ) {
238 NodeImpl *n = context->previousSibling();
241 n = n->previousSibling();
246 NodeImpl *p = context;
252 n = n->nextSibling();
259 NodeImpl *p = context;
261 NodeImpl *n = p->previousSibling();
265 n = n->previousSibling();
272 if ( context->nodeType() != Node::ELEMENT_NODE ) {
276 NamedAttrMapImpl *attrs =
static_cast<ElementImpl*
>(context)->attributes(
true );
281 for (
unsigned long i = 0; i < attrs->length(); ++i ) {
282 nodes->append( attrs->item( i ) );
290 if ( context->nodeType() != Node::ELEMENT_NODE ) {
294 bool foundXmlNsNode =
false;
295 NodeImpl *node = context;
297 NamedAttrMapImpl *attrs =
298 node->isElementNode() ?
static_cast<ElementImpl*
>(node)->attributes() : 0;
304 for (
unsigned long i = 0; i < attrs->length(); ++i ) {
305 NodeImpl *n = attrs->item( i );
306 if ( n->nodeName().string().startsWith(
"xmlns:" ) ) {
308 }
else if ( n->nodeName() ==
"xmlns" &&
311 foundXmlNsNode =
true;
312 if ( !n->nodeValue().string().isEmpty() ) {
323 nodes->append( context );
326 nodes->append( context );
330 nodes->append( context );
345 void Step::compileNodeTest(
bool htmlCompat)
const
347 m_compileState = htmlCompat ? CompiledForHTML : CompiledForXML;
349 if ( m_nodeTest ==
"*" ) {
350 m_nodeTestType = NT_Star;
351 }
else if ( m_nodeTest ==
"text()" ) {
352 m_nodeTestType = NT_Text;
353 }
else if ( m_nodeTest ==
"comment()" ) {
354 m_nodeTestType = NT_Comment;
355 }
else if ( m_nodeTest.
startsWith(
"processing-instruction" ) ) {
359 const int space = m_nodeTest.
find(
' ' );
361 param = m_nodeTest.
substring( space + 1 );
365 m_nodeTestType = NT_PI;
367 m_nodeTestType = NT_PI_Lit;
370 }
else if ( m_nodeTest ==
"node()" ) {
371 m_nodeTestType = NT_AnyNode;
377 splitPrefixLocalName( m_nodeTest, prefix, localName, htmlCompat );
379 if ( prefix.id() == DOM::emptyPrefix ) {
381 m_nodeTestType = NT_LocalName;
382 m_localName = localName;
383 }
else if ( localName.toString() ==
"*" ) {
385 m_nodeTestType = NT_Namespace;
386 m_namespace = NamespaceName::fromString(namespaceFromNodetest( m_nodeTest ) );
389 m_nodeTestType = NT_QName;
390 m_localName = localName;
391 m_namespace = NamespaceName::fromString(namespaceFromNodetest( m_nodeTest ) );
398 CompileState desired = ctx->htmlCompat() ? CompiledForHTML : CompiledForXML;
399 if ( m_compileState != desired )
400 compileNodeTest( ctx->htmlCompat() );
402 if ( m_nodeTestType == NT_AnyNode)
410 switch ( m_nodeTestType ) {
412 matchType = primaryNodeType( m_axis );
415 matchType = Node::COMMENT_NODE;
418 matchType = Node::TEXT_NODE;
422 matchType = Node::PROCESSING_INSTRUCTION_NODE;
428 if ( matchType != -1 ) {
429 for (
unsigned long n = 0; n < nodes->length(); ++n ) {
430 NodeImpl *node = nodes->item( n );
431 int nodeType = node->nodeType();
432 if ( nodeType == matchType ) {
433 if ( m_nodeTestType == NT_PI_Lit && node->nodeName() != m_piInfo )
436 matches->append( node );
439 if ( matchType == NT_Text && nodeType == Node::CDATA_SECTION_NODE )
440 matches->append( node );
448 matchType = primaryNodeType( m_axis );
449 for (
unsigned long n = 0; n < nodes->length(); ++n ) {
450 NodeImpl *node = nodes->item( n );
451 if ( node->nodeType() != matchType )
454 if ( m_nodeTestType == NT_LocalName ) {
455 if ( localNamePart( node->id() ) == m_localName.id() )
456 matches->append( node );
457 }
else if ( m_nodeTestType == NT_Namespace ) {
458 if ( namespacePart( node->id() ) == m_namespace.id() )
459 matches->append( node );
462 if ( node->id() == makeId( m_namespace.id(), m_localName.id() ) )
463 matches->append( node );
471 foreach(
Predicate *predicate, m_predicates ) {
479 foreach(
Predicate *predicate, m_predicates ) {
480 s += predicate->
dump();
488 int i = nodeTest.
find(
':' );
498 ns = resolver->lookupNamespaceURI( prefix );
506 unsigned int Step::primaryNodeType( AxisType axis )
const
510 return Node::ATTRIBUTE_NODE;
512 return Node::XPATH_NAMESPACE_NODE;
514 return Node::ELEMENT_NODE;
static bool areAdjacentTextNodes(NodeImpl *n, NodeImpl *m)
QString param(const QString &t)
static QString axisAsString(AxisType axis)
DOM::NodeImpl * nextSiblingForFollowing(DOM::NodeImpl *node)
SharedPtr< DOM::StaticNodeListImpl > DomNodeList
static DomNodeList compressTextNodes(const DomNodeList &nodes)
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
static void reportNamespaceErr()
bool isRootDomNode(NodeImpl *node)
static EvaluationContext & evaluationContext()
DomNodeList evaluate(DOM::NodeImpl *context) const
This class implements the basic string we use in the DOM.
DOM::NodeImpl * xpathFirstChild(DOM::NodeImpl *node)
void collectChildrenReverse(SharedPtr< DOM::StaticNodeListImpl > out, DOM::NodeImpl *root)
KAction * next(const QObject *recvr, const char *slot, QObject *parent)
bool startsWith(const DOMString &str) const
int find(const QChar c, int start=0) const
XPathNSResolverImpl * resolver
DOMString substring(unsigned pos, unsigned len=UINT_MAX) const
DOM::NodeImpl * xpathParentNode(DOM::NodeImpl *node)
void collectChildrenRecursively(SharedPtr< DOM::StaticNodeListImpl > out, DOM::NodeImpl *root)
static QDebug kWarning(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)