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>
|
2004-05-27 11:23:12 +02:00
|
|
|
#include <XML/UnicodeCharacters.h>
|
2007-07-19 19:01:08 +02:00
|
|
|
#include <Utils/uri.hpp>
|
2004-05-12 21:36:51 +02:00
|
|
|
|
|
|
|
namespace SAX
|
|
|
|
{
|
|
|
|
|
|
|
|
template<class string_type, class string_adaptor_type>
|
|
|
|
struct XMLBaseConstants
|
|
|
|
{
|
|
|
|
typedef string_type stringT;
|
|
|
|
typedef string_adaptor_type string_adaptorT;
|
|
|
|
|
|
|
|
const stringT xml;
|
|
|
|
const stringT xml_uri;
|
|
|
|
const stringT colon;
|
|
|
|
const stringT base;
|
|
|
|
|
|
|
|
XMLBaseConstants() :
|
2005-10-03 14:40:44 +02:00
|
|
|
xml(string_adaptorT().construct_from_utf8("xml")),
|
|
|
|
xml_uri(string_adaptorT().construct_from_utf8("http://www.w3.org/XML/1998/namespace")),
|
|
|
|
colon(string_adaptorT().construct_from_utf8(":")),
|
|
|
|
base(string_adaptorT().construct_from_utf8("base"))
|
2004-05-12 21:36:51 +02:00
|
|
|
{
|
|
|
|
} // XMLBaseConstants
|
|
|
|
}; // struct XMLBaseConstants
|
|
|
|
|
2005-08-15 23:09:13 +02:00
|
|
|
template<class string_type, class string_adaptor_type = Arabica::default_string_adaptor<string_type> >
|
2004-05-27 11:23:12 +02:00
|
|
|
class basic_XMLBaseSupport
|
2004-05-12 21:36:51 +02:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef string_type stringT;
|
2005-10-03 14:40:44 +02:00
|
|
|
typedef string_adaptor_type string_adaptorT;
|
2004-05-27 11:23:12 +02:00
|
|
|
typedef typename string_adaptor_type::value_type valueT;
|
2004-05-12 21:36:51 +02:00
|
|
|
typedef basic_Attributes<stringT> AttributesT;
|
|
|
|
|
2004-05-27 11:23:12 +02:00
|
|
|
basic_XMLBaseSupport() :
|
2005-10-03 14:40:44 +02:00
|
|
|
depth_(0) { }
|
2004-05-12 21:36:51 +02:00
|
|
|
|
|
|
|
void setDocumentLocation(const stringT& loc)
|
|
|
|
{
|
2007-07-19 19:01:08 +02:00
|
|
|
bases_.push(std::make_pair(-1, trim(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_;
|
2004-05-27 11:23:12 +02:00
|
|
|
stringT base = atts.getValue(xbc_.xml_uri, xbc_.base);
|
2004-05-12 21:36:51 +02:00
|
|
|
if(base.empty())
|
|
|
|
return;
|
|
|
|
|
2004-06-28 23:22:29 +02:00
|
|
|
stringT baseURI = absolutiseAndTrim(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-08-23 15:55:06 +02:00
|
|
|
stringT currentBase() const
|
|
|
|
{
|
|
|
|
if(!bases_.size())
|
|
|
|
return stringT();
|
|
|
|
return bases_.top().second;
|
|
|
|
} // currentBase()
|
|
|
|
|
|
|
|
stringT makeAbsolute(const stringT& 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-08-23 15:55:06 +02:00
|
|
|
stringT absolutise(const stringT& baseURI, const stringT& 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);
|
|
|
|
return string_adaptorT::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-06-28 23:22:29 +02:00
|
|
|
stringT absolutiseAndTrim(const stringT& baseURI, const stringT& location)
|
2007-07-19 19:01:08 +02:00
|
|
|
{
|
|
|
|
return trim(absolutise(baseURI, location));
|
|
|
|
} // absolutiseAndTrim
|
|
|
|
|
|
|
|
stringT trim(const stringT& location)
|
2004-06-28 23:22:29 +02:00
|
|
|
{
|
2005-10-03 14:40:44 +02:00
|
|
|
static const valueT FORWARD_SLASH = string_adaptorT::convert_from_utf8(Arabica::Unicode<char>::SLASH);
|
2004-06-28 23:22:29 +02:00
|
|
|
|
2007-07-19 19:01:08 +02:00
|
|
|
if(location[location.length()] == FORWARD_SLASH)
|
|
|
|
return location;
|
2004-06-28 23:22:29 +02:00
|
|
|
|
2007-07-19 19:01:08 +02:00
|
|
|
return location.substr(0, location.rfind(FORWARD_SLASH)+1);
|
|
|
|
} // trim
|
2004-06-28 23:22:29 +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, stringT> baseInfoT;
|
|
|
|
typedef std::stack<baseInfoT> baseStackT;
|
|
|
|
|
|
|
|
baseStackT bases_;
|
|
|
|
int depth_;
|
|
|
|
|
2005-10-03 14:40:44 +02:00
|
|
|
const XMLBaseConstants<stringT, string_adaptorT> xbc_;
|
2004-05-12 21:36:51 +02:00
|
|
|
|
|
|
|
// no impl
|
2004-05-27 11:23:12 +02:00
|
|
|
basic_XMLBaseSupport(const basic_XMLBaseSupport&);
|
|
|
|
basic_XMLBaseSupport& operator=(const basic_XMLBaseSupport&);
|
|
|
|
bool operator==(const basic_XMLBaseSupport&);
|
|
|
|
}; // class basic_XMLBaseSupport
|
|
|
|
|
|
|
|
typedef basic_XMLBaseSupport<std::string> XMLBaseSupport;
|
|
|
|
#ifndef ARABICA_NO_WCHAR_T
|
|
|
|
typedef basic_XMLBaseSupport<std::wstring> wXMLBaseSupport;
|
|
|
|
#endif
|
2004-05-27 10:28:26 +02:00
|
|
|
|
2004-05-12 21:36:51 +02:00
|
|
|
} // namespace SAX
|
|
|
|
|
2004-09-11 12:17:27 +02:00
|
|
|
#endif
|
|
|
|
|