arabica/include/SAX/helpers/XMLBaseSupport.hpp

127 lines
3.1 KiB
C++
Raw Normal View History

2004-05-12 21:36:51 +02:00
#ifndef ARABICA_XMLBASE_SUPPORT_H
#define ARABICA_XMLBASE_SUPPORT_H
/*
* $Id$
*
* XMLBaseSupport is a helper class for tracking xml:base attributes.
* Usage:
* set location of the containing document by calling setDocumentLocation
* this is usually done when during the setDocumentLocator SAX event
* forward each startElement and endElement event
* to resolve a relative URL against the current base, call makeAbsolute
*
* Derived from org.apache.cocoon.xml.XMLBaseSupport.
*
* XML Base is described at http://www.w3.org/TR/xmlbase/
*/
#include <stack>
#include <utility>
2004-05-27 10:28:26 +02:00
#include <sstream>
#include <text/UnicodeCharacters.hpp>
2007-09-10 17:58:45 +02:00
#include <io/uri.hpp>
2004-05-12 21:36:51 +02:00
2007-09-05 11:49:18 +02:00
namespace Arabica
{
2004-05-12 21:36:51 +02:00
namespace SAX
{
template<class string_type, class string_adaptor>
2004-05-12 21:36:51 +02:00
struct XMLBaseConstants
{
const string_type xml;
const string_type xml_uri;
const string_type colon;
const string_type base;
2004-05-12 21:36:51 +02:00
XMLBaseConstants() :
xml(string_adaptor::construct_from_utf8("xml")),
xml_uri(string_adaptor::construct_from_utf8("http://www.w3.org/XML/1998/namespace")),
colon(string_adaptor::construct_from_utf8(":")),
base(string_adaptor::construct_from_utf8("base"))
2004-05-12 21:36:51 +02:00
{
} // XMLBaseConstants
}; // struct XMLBaseConstants
template<class string_type, class string_adaptor = Arabica::default_string_adaptor<string_type> >
class XMLBaseSupport
2004-05-12 21:36:51 +02:00
{
public:
typedef typename string_adaptor::value_type valueT;
typedef Attributes<string_type, string_adaptor> AttributesT;
2004-05-12 21:36:51 +02:00
XMLBaseSupport() :
2005-10-03 14:40:44 +02:00
depth_(0) { }
2004-05-12 21:36:51 +02:00
void setDocumentLocation(const string_type& loc)
2004-05-12 21:36:51 +02:00
{
bases_.push(std::make_pair(-1, loc));
2004-05-12 21:36:51 +02:00
} // setDocumentLocation
2004-05-27 11:23:12 +02:00
void startElement(const AttributesT& atts)
2004-05-12 21:36:51 +02:00
{
++depth_;
string_type base = atts.getValue(xbc_.xml_uri, xbc_.base);
2004-05-12 21:36:51 +02:00
if(base.empty())
return;
string_type baseURI = absolutise(currentBase(), base);
2004-05-12 21:36:51 +02:00
bases_.push(std::make_pair(depth_, baseURI));
} // startElement
2004-05-27 11:23:12 +02:00
void endElement()
2004-05-12 21:36:51 +02:00
{
if(currentDepth() == depth_)
bases_.pop();
--depth_;
} // endElement
string_type currentBase() const
2007-08-23 15:55:06 +02:00
{
if(!bases_.size())
return string_type();
2007-08-23 15:55:06 +02:00
return bases_.top().second;
} // currentBase()
string_type makeAbsolute(const string_type& spec) const
2004-05-12 21:36:51 +02:00
{
2004-05-27 10:28:26 +02:00
return absolutise(currentBase(), spec);
2004-05-12 21:36:51 +02:00
} // makeAbsolute
private:
string_type absolutise(const string_type& baseURI, const string_type& location) const
2004-05-12 21:36:51 +02:00
{
2007-09-28 10:30:16 +02:00
Arabica::io::URI base(string_adaptor::asStdString(baseURI));
Arabica::io::URI absolute(base, string_adaptor::asStdString(location));
return string_adaptor::construct_from_utf8(absolute.as_string().c_str());
2004-05-27 10:28:26 +02:00
} // absolutise
2004-05-12 21:36:51 +02:00
2004-05-27 11:23:12 +02:00
int currentDepth() const
2004-05-12 21:36:51 +02:00
{
if(!bases_.size())
return -1;
return bases_.top().first;
} // currentDepths
private:
typedef std::pair<int, string_type> baseInfoT;
2004-05-12 21:36:51 +02:00
typedef std::stack<baseInfoT> baseStackT;
baseStackT bases_;
int depth_;
const XMLBaseConstants<string_type, string_adaptor> xbc_;
2004-05-12 21:36:51 +02:00
// no impl
XMLBaseSupport(const XMLBaseSupport&);
XMLBaseSupport& operator=(const XMLBaseSupport&);
bool operator==(const XMLBaseSupport&);
}; // class XMLBaseSupport
2004-05-27 10:28:26 +02:00
2004-05-12 21:36:51 +02:00
} // namespace SAX
2007-09-05 11:49:18 +02:00
} // namespace Arabica
2004-05-12 21:36:51 +02:00
#endif