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>
|
2007-09-05 00:55:47 +02:00
|
|
|
#include <XML/UnicodeCharacters.hpp>
|
2007-07-19 19:01:08 +02:00
|
|
|
#include <Utils/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
|
|
|
|
{
|
|
|
|
|
2007-09-06 00:08:51 +02:00
|
|
|
template<class string_type, class string_adaptor>
|
2004-05-12 21:36:51 +02:00
|
|
|
struct XMLBaseConstants
|
|
|
|
{
|
2007-09-06 00:08:51 +02:00
|
|
|
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() :
|
2007-09-06 00:08:51 +02:00
|
|
|
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
|
|
|
|
|
2007-09-06 00:08:51 +02:00
|
|
|
template<class string_type, class string_adaptor = Arabica::default_string_adaptor<string_type> >
|
2007-09-05 14:57:07 +02:00
|
|
|
class XMLBaseSupport
|
2004-05-12 21:36:51 +02:00
|
|
|
{
|
|
|
|
public:
|
2007-09-06 00:08:51 +02:00
|
|
|
typedef typename string_adaptor::value_type valueT;
|
|
|
|
typedef Attributes<string_type, string_adaptor> AttributesT;
|
2004-05-12 21:36:51 +02:00
|
|
|
|
2007-09-05 14:57:07 +02:00
|
|
|
XMLBaseSupport() :
|
2005-10-03 14:40:44 +02:00
|
|
|
depth_(0) { }
|
2004-05-12 21:36:51 +02:00
|
|
|
|
2007-09-06 00:08:51 +02:00
|
|
|
void setDocumentLocation(const string_type& loc)
|
2004-05-12 21:36:51 +02:00
|
|
|
{
|
2007-08-24 10:50:58 +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_;
|
2007-09-06 00:08:51 +02:00
|
|
|
string_type base = atts.getValue(xbc_.xml_uri, xbc_.base);
|
2004-05-12 21:36:51 +02:00
|
|
|
if(base.empty())
|
|
|
|
return;
|
|
|
|
|
2007-09-06 00:08:51 +02:00
|
|
|
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
|
|
|
|
|
2007-09-06 00:08:51 +02:00
|
|
|
string_type currentBase() const
|
2007-08-23 15:55:06 +02:00
|
|
|
{
|
|
|
|
if(!bases_.size())
|
2007-09-06 00:08:51 +02:00
|
|
|
return string_type();
|
2007-08-23 15:55:06 +02:00
|
|
|
return bases_.top().second;
|
|
|
|
} // currentBase()
|
|
|
|
|
2007-09-06 00:08:51 +02:00
|
|
|
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:
|
2007-09-06 00:08:51 +02:00
|
|
|
string_type absolutise(const string_type& baseURI, const string_type& location) const
|
2004-05-12 21:36:51 +02:00
|
|
|
{
|
2007-07-19 19:01:08 +02:00
|
|
|
Arabica::io::URI absolute(Arabica::io::URI(baseURI), location);
|
2007-09-06 00:08:51 +02:00
|
|
|
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:
|
2007-09-06 00:08:51 +02:00
|
|
|
typedef std::pair<int, string_type> baseInfoT;
|
2004-05-12 21:36:51 +02:00
|
|
|
typedef std::stack<baseInfoT> baseStackT;
|
|
|
|
|
|
|
|
baseStackT bases_;
|
|
|
|
int depth_;
|
|
|
|
|
2007-09-06 00:08:51 +02:00
|
|
|
const XMLBaseConstants<string_type, string_adaptor> xbc_;
|
2004-05-12 21:36:51 +02:00
|
|
|
|
|
|
|
// no impl
|
2007-09-05 14:57:07 +02:00
|
|
|
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
|
|
|
|
2004-09-11 12:17:27 +02:00
|
|
|
#endif
|
|
|
|
|