mirror of
https://bitbucket.org/smil3y/kdelibs.git
synced 2025-02-24 19:02:48 +00:00
255 lines
7.5 KiB
C++
255 lines
7.5 KiB
C++
/*
|
|
* dom3_xpathimpl.cpp - Copyright 2005 Frerich Raabe <raabe@kde.org>
|
|
* Copyright 2010 Maksim Orlovich <maksim@kde.org>
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
#include <dom/dom_exception.h>
|
|
#include <dom/dom3_xpath.h>
|
|
#include <xml/dom3_xpathimpl.h>
|
|
#include <xml/dom_nodeimpl.h>
|
|
#include <xml/dom_nodelistimpl.h>
|
|
|
|
#include "xpath/expression.h"
|
|
#include "xpath/util.h"
|
|
|
|
using namespace DOM;
|
|
using namespace khtml;
|
|
using namespace khtml::XPath;
|
|
using namespace DOM::XPath;
|
|
|
|
XPathResultImpl::XPathResultImpl()
|
|
{
|
|
}
|
|
|
|
XPathResultImpl::XPathResultImpl( const Value &value )
|
|
: m_value( value )
|
|
{
|
|
switch ( m_value.type() ) {
|
|
case Value::Boolean:
|
|
m_resultType = BOOLEAN_TYPE;
|
|
break;
|
|
case Value::Number:
|
|
m_resultType = NUMBER_TYPE;
|
|
break;
|
|
case Value::String:
|
|
m_resultType = STRING_TYPE;
|
|
break;
|
|
case Value::Nodeset:
|
|
m_resultType = UNORDERED_NODE_ITERATOR_TYPE;
|
|
m_nodeIterator = 0;
|
|
}
|
|
}
|
|
|
|
void XPathResultImpl::convertTo( unsigned short type, int &exceptioncode )
|
|
{
|
|
switch ( type ) {
|
|
case ANY_TYPE:
|
|
break;
|
|
case NUMBER_TYPE:
|
|
m_resultType = type;
|
|
m_value = Value( m_value.toNumber() );
|
|
break;
|
|
case STRING_TYPE:
|
|
m_resultType = type;
|
|
m_value = Value( m_value.toString() );
|
|
break;
|
|
case BOOLEAN_TYPE:
|
|
m_resultType = type;
|
|
m_value = Value( m_value.toBoolean() );
|
|
break;
|
|
case UNORDERED_NODE_ITERATOR_TYPE:
|
|
case ORDERED_NODE_ITERATOR_TYPE:
|
|
case UNORDERED_NODE_SNAPSHOT_TYPE:
|
|
case ORDERED_NODE_SNAPSHOT_TYPE:
|
|
case ANY_UNORDERED_NODE_TYPE:
|
|
case FIRST_ORDERED_NODE_TYPE:
|
|
if ( !m_value.isNodeset() ) {
|
|
exceptioncode = XPathException::toCode(XPathException::TYPE_ERR);
|
|
return;
|
|
}
|
|
m_resultType = type;
|
|
break;
|
|
default:
|
|
kDebug(6011) << "Cannot convert XPathResultImpl to unknown type" << type;
|
|
exceptioncode = XPathException::toCode(XPathException::TYPE_ERR);
|
|
}
|
|
}
|
|
|
|
unsigned short XPathResultImpl::resultType() const
|
|
{
|
|
return m_resultType;
|
|
}
|
|
|
|
double XPathResultImpl::numberValue(int &exceptioncode) const
|
|
{
|
|
if ( resultType() != NUMBER_TYPE ) {
|
|
exceptioncode = XPathException::toCode(XPathException::TYPE_ERR);
|
|
return 0.0;
|
|
}
|
|
return m_value.toNumber();
|
|
}
|
|
|
|
DOM::DOMString XPathResultImpl::stringValue(int &exceptioncode) const
|
|
{
|
|
if ( resultType() != STRING_TYPE ) {
|
|
exceptioncode = XPathException::toCode(XPathException::TYPE_ERR);
|
|
return DOMString();
|
|
}
|
|
return m_value.toString();
|
|
}
|
|
|
|
bool XPathResultImpl::booleanValue(int &exceptioncode) const
|
|
{
|
|
if ( resultType() != BOOLEAN_TYPE ) {
|
|
exceptioncode = XPathException::toCode(XPathException::TYPE_ERR);
|
|
return false;
|
|
}
|
|
return m_value.toBoolean();
|
|
}
|
|
|
|
NodeImpl *XPathResultImpl::singleNodeValue(int &exceptioncode) const
|
|
{
|
|
if ( resultType() != ANY_UNORDERED_NODE_TYPE &&
|
|
resultType() != FIRST_ORDERED_NODE_TYPE ) {
|
|
exceptioncode = XPathException::toCode(XPathException::TYPE_ERR);
|
|
return 0;
|
|
}
|
|
DomNodeList nodes = m_value.toNodeset();
|
|
|
|
if (nodes && nodes->length())
|
|
return nodes->item(0);
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
bool XPathResultImpl::invalidIteratorState() const
|
|
{
|
|
if ( resultType() != UNORDERED_NODE_ITERATOR_TYPE &&
|
|
resultType() != ORDERED_NODE_ITERATOR_TYPE ) {
|
|
return false;
|
|
}
|
|
// XXX How to tell whether the document was changed since this
|
|
// result was returned?
|
|
return true;
|
|
}
|
|
|
|
unsigned long XPathResultImpl::snapshotLength(int &exceptioncode) const
|
|
{
|
|
if ( resultType() != UNORDERED_NODE_SNAPSHOT_TYPE &&
|
|
resultType() != ORDERED_NODE_SNAPSHOT_TYPE ) {
|
|
exceptioncode = XPathException::toCode(XPathException::TYPE_ERR);
|
|
return 0;
|
|
}
|
|
|
|
SharedPtr<DOM::StaticNodeListImpl> nodes = m_value.toNodeset();
|
|
return nodes ? nodes->length() : 0;
|
|
}
|
|
|
|
NodeImpl *XPathResultImpl::iterateNext(int &exceptioncode)
|
|
{
|
|
if ( resultType() != UNORDERED_NODE_ITERATOR_TYPE &&
|
|
resultType() != ORDERED_NODE_ITERATOR_TYPE ) {
|
|
exceptioncode = XPathException::toCode(XPathException::TYPE_ERR);
|
|
return 0;
|
|
}
|
|
// XXX How to tell whether the document was changed since this
|
|
// result was returned? We need to throw an INVALID_STATE_ERR if that
|
|
// is the case.
|
|
SharedPtr<DOM::StaticNodeListImpl> nodes = m_value.toNodeset();
|
|
if ( !nodes || m_nodeIterator >= nodes->length() ) {
|
|
return 0;
|
|
} else {
|
|
NodeImpl* n = nodes->item(m_nodeIterator);
|
|
++m_nodeIterator;
|
|
return n;
|
|
}
|
|
}
|
|
|
|
NodeImpl *XPathResultImpl::snapshotItem( unsigned long index, int &exceptioncode )
|
|
{
|
|
if ( resultType() != UNORDERED_NODE_SNAPSHOT_TYPE &&
|
|
resultType() != ORDERED_NODE_SNAPSHOT_TYPE ) {
|
|
exceptioncode = XPathException::toCode(XPathException::TYPE_ERR);
|
|
return 0;
|
|
}
|
|
DomNodeList nodes = m_value.toNodeset();
|
|
if ( !nodes || index >= nodes->length() ) {
|
|
return 0;
|
|
}
|
|
return nodes->item( index );
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
DefaultXPathNSResolverImpl::DefaultXPathNSResolverImpl( NodeImpl *node )
|
|
: m_node( node )
|
|
{
|
|
}
|
|
|
|
DOMString DefaultXPathNSResolverImpl::lookupNamespaceURI( const DOMString& prefix )
|
|
{
|
|
// Apparently Node::lookupNamespaceURI doesn't do this.
|
|
// ### check
|
|
if ( prefix.string() == "xml" ) {
|
|
return DOMString( "http://www.w3.org/XML/1998/namespace" );
|
|
}
|
|
return m_node->lookupNamespaceURI( prefix );
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
XPathExpressionImpl::XPathExpressionImpl( const DOMString& expression, XPathNSResolverImpl *resolver ): m_statement(expression, resolver)
|
|
{
|
|
}
|
|
|
|
XPathResultImpl *XPathExpressionImpl::evaluate( NodeImpl *contextNode,
|
|
unsigned short type,
|
|
XPathResultImpl* /*result_*/,
|
|
int &exceptioncode )
|
|
{
|
|
if ( !isValidContextNode( contextNode ) ) {
|
|
exceptioncode = DOMException::NOT_SUPPORTED_ERR;
|
|
return 0;
|
|
}
|
|
|
|
// We are permitted, but not required, to re-use result_. We don't.
|
|
Value xpathRes = m_statement.evaluate( contextNode, exceptioncode );
|
|
XPathResultImpl* result = new XPathResultImpl( exceptioncode ? Value() : xpathRes );
|
|
|
|
if ( type != ANY_TYPE ) {
|
|
result->convertTo( type, exceptioncode );
|
|
if( exceptioncode ) {
|
|
kDebug(6011) << "couldn't convert XPathResult to" << type << "from" << xpathRes.type();
|
|
delete result;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
int XPathExpressionImpl::parseExceptionCode()
|
|
{
|
|
return m_statement.exceptionCode();
|
|
}
|
|
|
|
// kate: indent-width 4; replace-tabs off; tab-width 4; space-indent off;
|