arabica/SAX/helpers/XMLBaseSupport.h

165 lines
4.2 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>
2004-05-27 11:23:12 +02:00
#include <XML/UnicodeCharacters.h>
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() :
xml(string_adaptorT().makeStringT("xml")),
xml_uri(string_adaptorT().makeStringT("http://www.w3.org/XML/1998/namespace")),
colon(string_adaptorT().makeStringT(":")),
base(string_adaptorT().makeStringT("base"))
{
} // XMLBaseConstants
}; // struct XMLBaseConstants
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;
2004-05-27 10:28:26 +02:00
typedef string_adaptor_type stringAdaptorT;
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() :
depth_(0), SA_() { }
2004-05-12 21:36:51 +02:00
void setDocumentLocation(const stringT& loc)
{
bases_.push(std::make_pair(-1, loc));
} // 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;
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
stringT makeAbsolute(const stringT& spec)
{
2004-05-27 10:28:26 +02:00
return absolutise(currentBase(), spec);
2004-05-12 21:36:51 +02:00
} // makeAbsolute
private:
2004-05-27 11:23:12 +02:00
stringT absolutise(const stringT& baseURI, const stringT& location)
2004-05-12 21:36:51 +02:00
{
2004-05-27 10:28:26 +02:00
static const stringT SCHEME_MARKER = SA_.makeStringT("://");
2004-05-27 11:23:12 +02:00
static const valueT FORWARD_SLASH = SA_.makeValueT(Arabica::Unicode<char>::SLASH);
2004-05-27 10:28:26 +02:00
if(location.find(SCHEME_MARKER) != stringT::npos)
2004-05-27 10:28:26 +02:00
return location;
std::ostringstream ss;
if(location[0] == FORWARD_SLASH)
2004-05-27 10:28:26 +02:00
{
2004-05-27 13:48:14 +02:00
// prepend URI scheme and location
size_t schemeLen = baseURI.find(SCHEME_MARKER) + SCHEME_MARKER.length();
ss << baseURI.substr(0, baseURI.find(FORWARD_SLASH, schemeLen+1));
2004-05-27 10:28:26 +02:00
}
else
{
// relative
ss << baseURI;
if(baseURI.find(FORWARD_SLASH) == baseURI.length()-1)
ss << FORWARD_SLASH;
}
ss << location;
return SA_.makeStringT(ss.str().c_str());
} // absolutise
2004-05-12 21:36:51 +02:00
stringT absolutiseAndTrim(const stringT& baseURI, const stringT& location)
{
static const valueT FORWARD_SLASH = SA_.makeValueT(Arabica::Unicode<char>::SLASH);
stringT newlocation = absolutise(baseURI, location);
if(newlocation[newlocation.length()] == FORWARD_SLASH)
return newlocation;
return newlocation.substr(0, newlocation.rfind(FORWARD_SLASH)+1);
} // absolutiseAndTrim
2004-05-27 11:23:12 +02:00
stringT currentBase() const
2004-05-12 21:36:51 +02:00
{
if(!bases_.size())
return stringT();
return bases_.top().second;
} // currentBase()
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_;
2004-05-27 10:28:26 +02:00
stringAdaptorT SA_;
2004-05-12 21:36:51 +02:00
2004-05-27 11:23:12 +02:00
const XMLBaseConstants<stringT, stringAdaptorT> 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
#endif